28

Python には、既に存在する場合にファイル名に番号を追加する機能が組み込まれていますか?

私の考えでは、特定の OS の動作と同じように機能するということです。ファイルがその名前のファイルが既に存在するディレクトリに出力される場合、番号が追加されるか、それがインクリメントされます。

つまり、「file.pdf」が存在する場合、「file2.pdf」が作成され、次に「file3.pdf」が作成されます。

4

14 に答える 14

14

ある意味では、Python にはこの機能がモジュールに組み込まれていtempfileます。残念ながら、プライベート グローバル変数を利用する必要がありますtempfile._name_sequence。これは、正式にtempfileは、将来のバージョンでも存在することを保証するものではなく_name_sequence、実装の詳細であることを意味します。ただし、とにかく使用しても問題ない場合は、次のfile#.pdfような指定されたディレクトリにフォームの一意の名前のファイルを作成する方法を示してい/tmpます。

import tempfile
import itertools as IT
import os

def uniquify(path, sep = ''):
    def name_sequence():
        count = IT.count()
        yield ''
        while True:
            yield '{s}{n:d}'.format(s = sep, n = next(count))
    orig = tempfile._name_sequence 
    with tempfile._once_lock:
        tempfile._name_sequence = name_sequence()
        path = os.path.normpath(path)
        dirname, basename = os.path.split(path)
        filename, ext = os.path.splitext(basename)
        fd, filename = tempfile.mkstemp(dir = dirname, prefix = filename, suffix = ext)
        tempfile._name_sequence = orig
    return filename

print(uniquify('/tmp/file.pdf'))
于 2012-12-13T04:16:18.903 に答える
3

これらのファイルが既にあるとします。

ここに画像の説明を入力

この関数は、必要に応じて拡張子の前に _1、_2、_3、... の接尾辞を追加することにより、次の使用可能なまだ存在しない filenameを生成します。

import os

def nextnonexistent(f):
    fnew = f
    root, ext = os.path.splitext(f)
    i = 0
    while os.path.exists(fnew):
        i += 1
        fnew = '%s_%i%s' % (root, i, ext)
    return fnew

print(nextnonexistent('foo.txt'))  # foo_3.txt
print(nextnonexistent('bar.txt'))  # bar_1.txt
print(nextnonexistent('baz.txt'))  # baz.txt
于 2020-05-02T14:47:27.070 に答える
2

一時ファイルのハック A) はハックであり、B) とにかくかなりの量のコードが必要であるため、手動で実装しました。基本的に必要なもの:

  1. ファイルが存在しない場合にのみ、ファイルを安全に作成する方法(これは、一時ファイルのハックが提供するものです)。
  2. ファイル名のジェネレータ。
  3. ごちゃごちゃを隠すラッピング機能。

open と同じように使用できる safe_open を定義しました。

def iter_incrementing_file_names(path):
    """
    Iterate incrementing file names. Start with path and add " (n)" before the
    extension, where n starts at 1 and increases.

    :param path: Some path
    :return: An iterator.
    """
    yield path
    prefix, ext = os.path.splitext(path)
    for i in itertools.count(start=1, step=1):
        yield prefix + ' ({0})'.format(i) + ext


def safe_open(path, mode):
    """
    Open path, but if it already exists, add " (n)" before the extension,
    where n is the first number found such that the file does not already
    exist.

    Returns an open file handle. Make sure to close!

    :param path: Some file name.

    :return: Open file handle... be sure to close!
    """
    flags = os.O_CREAT | os.O_EXCL | os.O_WRONLY

    if 'b' in mode and platform.system() == 'Windows':
        flags |= os.O_BINARY

    for filename in iter_incrementing_file_names(path):
        try:
            file_handle = os.open(filename, flags)
        except OSError as e:
            if e.errno == errno.EEXIST:
                pass
            else:
                raise
        else:
            return os.fdopen(file_handle, mode)

# Example
with safe_open("some_file.txt", "w") as fh:
    print("Hello", file=fh)
于 2015-12-10T02:12:32.173 に答える
0

os.path.exists() 条件付き関数が必要なことを行っていることがわかりました。例として辞書から CSV への保存を使用していますが、同じロジックがどのファイル タイプでも機能します。

import os 

def smart_save(filename, dict):
    od = filename + '_' # added underscore before number for clarity

    for i in np.arange(0,500,1): # I set an arbitrary upper limit of 500
        d = od + str(i)

        if os.path.exists(d + '.csv'):
            pass

        else:
            with open(d + '.csv', 'w') as f: #or any saving operation you need
                for key in dict.keys():
                    f.write("%s,%s\n"%(key, dictionary[key]))
            break

注: これにより、デフォルトでファイル名に番号 (0 から始まる) が追加されますが、簡単に変更できます。

于 2019-09-20T01:27:32.897 に答える
-1

私は同様のソリューションを実装しましたpathlib

パターンに一致するファイル名を作成しますpath/<file-name>-\d\d.ext。おそらく、このソリューションが役立つ可能性があります...

import pathlib
from toolz import itertoolz as itz

def file_exists_add_number(path_file_name, digits=2):

    pfn = pathlib.Path(path_file_name)
    parent = pfn.parent     # parent-dir of file
    stem = pfn.stem         # file-name w/o extension
    suffix = pfn.suffix     # NOTE: extension starts with '.' (dot)!

    try:
        # search for files ending with '-\d\d.ext'
        last_file = itz.last(parent.glob(f"{stem}-{digits * '?'}{suffix}"))
    except:
        curr_no = 1
    else:
        curr_no = int(last_file.stem[-digits:]) + 1

    # int to string and add leading zeros
    curr_no = str(last_no).zfill(digits)
    path_file_name = parent / f"{stem}-{curr_no}{suffix}"

    return str(path_file_name)

Pls note: このソリューションは で始まり、!01を含むファイル パターンのみを検出します。-\d\d

于 2019-09-11T07:38:40.510 に答える
-3

この名前がフォルダーにある場合、新しいファイルを作成する簡単な方法

if 'sample.xlsx' in os.listdir('testdir/'):

    i = 2
    
    while os.path.exists(f'testdir/sample ({i}).xlsx'):
        i += 1
    
    wb.save(filename=f"testdir/sample ({i}).xlsx")
else:
    wb.save(filename=f"testdir/sample.xlsx")

于 2021-03-12T21:18:47.737 に答える