Автоинкрементные имена файлов - PullRequest
0 голосов
/ 10 декабря 2018

Эта проблема возникает из [здесь] .Я пытался спросить об этом по предоставленной ссылке, но мне отказали в голосовании и сказали, что я должен задать свой вопрос ... вот и я.

Я попытался воспроизвести результаты для своего собственного проекта, и это не сработало.когда я пытаюсь сохранить более двух файлов, сценарий начинает переименовывать каждый файл вместо только что созданных мной новых:

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)

Заранее благодарю за помощь!

1 Ответ

0 голосов
/ 10 декабря 2018

Причина, по которой вы получаете такое поведение, заключается в том, что os.walk возвращается в подкаталоги.Ваш целевой каталог IS является подкаталогом вашего источника - поэтому вы переименовываете файлы из source в target и позже os.walk в target и переименуйте его в сам , используя стратегию «переименования» все время, потому что файл уже существует.


Длинное решение - большая часть его создает файловые структуры, так что это Пример минимального, полного и проверяемого значения , который вы можете использовать.

См. Документацию topdown=False в os.walk

Создать файловую структуру

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 в своем названии, потому что файл с таким же именем уже был в нем.

...