自动递增文件名

Autoincrement file names

这个问题来自[here]。我试着询问这是 link 提供的,但我被否决并被告知要问我自己的问题......所以我在这里。

我尝试为我自己的项目复制结果,但没有成功。当我尝试保存两个以上的文件时,脚本开始重命名每个文件,而不仅仅是我创建的新文件:

file_1_2_2_1_4_4_6_2_2.pdf
file1_3_2_3_3-6_5_1.pdf
file2_1_1_1-7_3_9.pdf
etc

而不是

file_1.pdf
file_2.pdf
file_3.pdf
etc.

有什么建议吗?

def save_file():
    path = "/home/PycharmProjects/untitled/screening/"
    newPath = "/home/PycharmProjects/untitled/screening/finished"
    i = 1
    for root, dirs, files in os.walk(path):

        for name in files:
            base, extension = os.path.splitext(name)
            if not os.path.exists(os.path.join(newPath, base + extension)):
                oldfile = os.path.join(os.path.abspath(root), name)
                newfile = os.path.join(newPath, base + extension)
                os.rename(oldfile, newfile)
            else:
                oldfile = os.path.join(os.path.abspath(root), name)
                newfile = os.path.join(newPath, base + '_' + str(i) + extension)
                i += 1
                os.rename(oldfile, newfile)

预先感谢您的帮助!

出现此行为的原因是 os.walk 递归到子目录中。你的目标目录 IS 你的 sourcedir 的一个子目录 - 所以你将文件从 source 重命名为 target 及以后os.walk 进入 target 目录,并一直使用 "renaming" 策略将更多内容重命名为 itself,因为文件已经存在。


冗长的解决方案 - 其中大部分是创建文件结构,因此这是一个 Minimal, Complete, and Verifiable example 您可以使用的解决方案。

请参阅 os.walk

topdown=False 的文档

创建文件结构

import os
files = [ f"file_{i:05}x.txt" for i in range(20)]

org = os.path.abspath("./dir1/dir2/")
new = os.path.abspath("./dir1/dir2/new/")
os.makedirs(new)
# create all in org
for f in files:
    with open(os.path.join(org,f),"w") as f:
        f.write(" ")
#create every 4th one in new 
for f in files[::4]:
    with open(os.path.join(new,f),"w") as f:
        f.write(" ")

for root,dirs,files in os.walk(org):
    print(root)
    print(" [d] ", dirs)
    print(" [f] ", sorted(files))

输出:

/tmp/dir1/dir2
 [d]  ['new']
 [f]  ['file_00000x.txt', 'file_00001x.txt', 'file_00002x.txt', 'file_00003x.txt',
       'file_00004x.txt', 'file_00005x.txt', 'file_00006x.txt', 'file_00007x.txt', 
       'file_00008x.txt', 'file_00009x.txt', 'file_00010x.txt', 'file_00011x.txt', 
       'file_00012x.txt', 'file_00013x.txt', 'file_00014x.txt', 'file_00015x.txt', 
       'file_00016x.txt', 'file_00017x.txt', 'file_00018x.txt', 'file_00019x.txt']
/tmp/dir1/dir2/new
 [d]  []
 [f]  ['file_00000x.txt', 'file_00004x.txt', 'file_00008x.txt', 'file_00012x.txt', 
       'file_00016x.txt']

固定方法

def save_file(old_path, new_path):

    # topdown = False allows to modify the results to NOT recurse

    for root, dirs, files in os.walk(old_path, topdown=False):
        dirs = [] # do not recurse into subdirs ( whereto we copy the stuff )
        root_abs = os.path.abspath(root)
        new_abs = os.path.abspath(new_path)

        for name in sorted(files):  # sorting is convenience, not needed
            old_file = os.path.join(root_abs, name)
            new_file = os.path.join(new_abs, name)

            # fix renaming logic (simplified) - looks until a unique name is found
            i = 1
            base, extension = os.path.splitext(name)
            while os.path.exists(new_file):  
                # create a new name if it already exists 
                new_file = os.path.join(new_abs, f"{base}_{i}{extension}")
                i += 1 

            # do the copy over
            os.rename(old_file, new_file)

用法:

# uses the org/new from above
# org = os.path.abspath("./dir1/dir2/")
# new = os.path.abspath("./dir1/dir2/new/")

save_file(org,new)

for root,dirs,files in os.walk(org):
    print(root)
    print(" [d] ", dirs)
    print(" [f] ", sorted(files))

之后输出:

/tmp/dir1/dir2
 [d]  ['new']
 [f]  []
/tmp/dir1/dir2/new
 [d]  []
 [f]  ['file_00000x.txt', 'file_00000x_1.txt', 'file_00001x.txt', 'file_00002x.txt', 
       'file_00003x.txt', 'file_00004x.txt', 'file_00004x_1.txt', 'file_00005x.txt', 
       'file_00006x.txt', 'file_00007x.txt', 'file_00008x.txt', 'file_00008x_1.txt', 
       'file_00009x.txt', 'file_00010x.txt', 'file_00011x.txt', 'file_00012x.txt', 
       'file_00012x_1.txt', 'file_00013x.txt', 'file_00014x.txt', 'file_00015x.txt', 
       'file_00016x.txt', 'file_00016x_1.txt', 'file_00017x.txt', 'file_00018x.txt', 
       'file_00019x.txt']

您看到 new 中的某些文件在其名称中获得了 _1 中缀,因为其中已经存在同名文件。