python: Create file but if name exists add number
python对此有任何内置功能吗?我的想法是,如果一个文件被输出到一个已经存在同名文件的目录中,它将像某些操作系统的工作方式一样工作。例如:如果"file.pdf"存在,它将创建"file2.pdf",下次创建"file3.pdf"。
在某种程度上,python在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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')) |
我试图在我的项目中实现相同的东西,但是@unutbu的答案对于我的需求来说太"沉重",所以我最终想出了以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 | 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 |
以防有人偶然发现这一点,需要更简单的东西。
最近我遇到了同样的事情,下面是我的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 |
因为tempfile hack a)是一个hack,b)仍然需要相当数量的代码,所以我使用了手动实现。你基本上需要:
我定义了一个可以像打开一样使用的安全打开:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | 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) |
这对我有用。初始文件名为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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 |
我还没有测试过这个,但是它应该可以工作,迭代可能的文件名,直到问题文件不存在,它在哪一点中断。
1 2 3 4 5 6 7 8 9 10 11 | 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 |
稍晚一点,但仍然有这样的东西应该正常工作,MB它将对某人有用。
您可以使用内置迭代器进行此操作(以图像下载器为例):
1 2 3 4 5 6 7 8 9 | def image_downloader(): image_url = 'some_image_url' for count in range(10): image_data = requests.get(image_url).content with open(f'image_{count}.jpg', 'wb') as handler: handler.write(image_data) |
文件将正确递增。结果是:
1 2 3 4 5 6 7 8 9 10 11 | image.jpg image_0.jpg image_1.jpg image_2.jpg image_3.jpg image_4.jpg image_5.jpg image_6.jpg image_7.jpg image_8.jpg image_9.jpg |