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