创建文件,但如果存在名称,则添加编号

问题描述 投票:16回答:12

Python是否具有任何内置功能可在文件名中添加数字(如果已经存在?)>

[我的想法是,它将以某些OS的工作方式工作-如果将文件输出到已经存在该名称的文件的目录中,它将添加一个数字或对其进行递增。

即:如果存在“ file.pdf”,它将创建“ file2.pdf”,并且下次创建“ file3.pdf”。

Python是否有任何内置功能可将数字添加到文件名(如果已经存在?我的想法是,它将以某些OS的工作方式工作-如果将文件输出到......>

python file-io operating-system
12个回答
13
投票

以某种方式,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'))

0
投票

我用pathlib实现了类似的解决方案:

创建与模式path/<file-name>-\d\d.ext匹配的文件名。也许此解决方案可以帮助...


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开始),但是很容易转移。


-1
投票

过了一会儿,但是仍然有类似的东西应该可以正常工作,它对某人有用。


4
投票

我试图在我的项目中实现相同的功能,但是@unutbu的回答似乎太“繁重”,无法满足我的需求,所以我最终想出了以下代码:

import os
index = ''
while True:
    try:
        os.makedirs('../hi'+index)
        break
    except WindowsError:
        if index:
            index = '('+str(int(index[1:-1])+1)+')' # Append 1 to number in brackets
        else:
            index = '(1)'
        pass # Go and try create file again

3
投票

由于tempfile hack A)是hack,而B)仍然需要大量的代码,因此我采用了手动实现。您基本上需要:

  1. Safely create a file if and only if it does not exist的一种方式(这是临时文件破解为我们提供的。)>
  2. 文件名生成器。

3
投票

最近我遇到了同样的事情,这是我的方法:

import os

file_name = "file_name.txt"
if os.path.isfile(file_name):
    expand = 1
    while True:
        expand += 1
        new_file_name = file_name.split(".txt")[0] + str(expand) + ".txt"
        if os.path.isfile(new_file_name):
            continue
        else:
            file_name = new_file_name
            break

3
投票

如果所有被编号的文件都没问题,并且您事先知道要写入的文件的名称,您可以简单地做:

import os

counter = 0
filename = "file{}.pdf"
while os.path.isfile(filename.format(counter)):
    counter += 1
filename = filename.format(counter)

1
投票

我最终为此编写了自己的简单函数。原始,但是可以完成工作:

def uniquify(path):
    filename, extension = os.path.splitext(path)
    counter = 1

    while os.path.exists(path):
        path = filename + " (" + str(counter) + ")" + extension
        counter += 1

    return path

0
投票

我还没有对此进行测试,但是它应该可以工作,遍历可能的文件名,直到所讨论的文件不存在时为止。”

def increment_filename(fn):
    fn, extension = os.path.splitext(path)

    n = 1
    yield fn + extension
    for n in itertools.count(start=1, step=1)
        yield '%s%d.%s' % (fn, n, extension)

for filename in increment_filename(original_filename):
    if not os.isfile(filename):
        break

0
投票

这对我有用。初始文件名为0.yml,如果存在,它将添加一个文件,直到满足要求。

import os
import itertools

def increment_filename(file_name):
    fid, extension = os.path.splitext(file_name)

    yield fid + extension
    for n in itertools.count(start=1, step=1):
        new_id = int(fid) + n
        yield "%s%s" % (new_id, extension)


def get_file_path():
    target_file_path = None
    for file_name in increment_filename("0.yml"):
        file_path = os.path.join('/tmp', file_name)
        if not os.path.isfile(file_path):
            target_file_path = file_path
            break
    return target_file_path

0
投票
import os

class Renamer():
    def __init__(self, name):
        self.extension = name.split('.')[-1]
        self.name = name[:-len(self.extension)-1]
        self.filename = self.name
    def rename(self):
        i = 1
        if os.path.exists(self.filename+'.'+self.extension):
            while os.path.exists(self.filename+'.'+self.extension):
                self.filename = '{} ({})'.format(self.name,i)
                i += 1
        return self.filename+'.'+self.extension
© www.soinside.com 2019 - 2024. All rights reserved.