#python
#python
Вопрос:
У меня есть папка с несколькими вложенными папками, в каждой из которых находится файл. Я работаю на python и хотел бы переименовать файл с соответствующим именем вложенной папки плюс старое имя файла в новое имя файла.
Мне удалось получить список вложенных папок и имен файлов os.walk()
, но у меня возникли проблемы с изменением имени файла.
def list_files(dir):
r = []
for root, dirs, files in os.walk(dir):
for name in files:
r.append(os.path.join(root, name))
os.rename(name, r)
Я получаю сообщение об ошибке:
Ошибка типа: переименовать: dst должно быть строкой, байтами или os.Похожий на путь, а не на список
Когда я возвращаю r, я получаю корень и имя файла, но не могу изменить имя файла. Ценю любую помощь.
Ответ №1:
import os
def list_files(dir):
sub_folders = os.listdir(dir)
for sub_folder in sub_folders:
sub_folder_path = os.path.join(dir,sub_folder)
for root, dirs, files in os.walk(sub_folder_path):
for file in files:
new_filename = root.replace(dir, "").replace(os.path.sep,"_").strip("_") "_" file
os.rename(os.path.join(root, file), os.path.join(root, new_filename))
input_dir = ""
assert os.path.isdir(input_dir),"Enter a valid directory path which consists of sub-directories"
list_files(input_dir)
Это выполнит работу для нескольких подкаталогов, а не для вложенных каталогов. Если вы хотите изменить, каким должно быть имя файла, измените строку new_filename = sub_folder "" file
.
Комментарии:
1. Ваш код выглядит хорошо. Я дал ему преимущество. Однако обратите внимание, что это не удается, если в каталогах верхнего уровня есть каталоги, содержащие файлы. Я думаю, это потому, что walk попытается спуститься на несколько уровней, но что-то не совсем правильно, когда он это делает.
2. Спасибо, Вкредди, это сработало, но по какой-то причине поместите имя каталога дважды в новое имя файла. Я все еще пытаюсь понять, почему это так.
3. Обновлен код с исправлениями, упомянутыми @Steve. Спасибо!
Ответ №2:
Вот аналогичный ответ на @VkreddyKomatireddy, но он используется listdir()
на обоих уровнях, а также проверяет и игнорирует более глубоко вложенные каталоги на первом уровне подкаталогов.
Вот мой код, хорошо аннотированный:
import os
def collapse_dirs(dir):
# get a list of elements in the target directory
elems = os.listdir(dir)
# iterate over each element
for elem in elems:
# compute the path to the element
path = os.path.join(dir, elem)
# is it a directory? If so, process it...
if os.path.isdir(path):
# get all of the elements in the subdirectory
subelems = os.listdir(path)
# process each entry in this subdirectory...
for subelem in subelems:
# compute the full path to the element
filepath = os.path.join(path, subelem)
# we only want to proceed if the element is a file. If so...
if os.path.isfile(filepath):
# compute the new path for the file - I chose to separate the names with an underscore,
# but this line can easily be changed to use whatever separator you want (or none)
newpath = os.path.join(path, elem '_' subelem)
# rename the file
os.rename(filepath, newpath)
def main():
collapse_dirs('/tmp/filerename2')
main()
Вот мой целевой каталог перед запуском кода:
filerename2
├── a
│ └── xxx.txt
├── b
│ ├── xxx.txt
│ └── yyyy
│ └── zzzz
├── c
│ └── xxx.txt
└── xxxx
и вот это после:
filerename2
├── a
│ └── a_xxx.txt
├── b
│ ├── b_xxx.txt
│ └── yyyy
│ └── zzzz
├── c
│ └── c_xxx.txt
└── xxxx
Комментарии:
1. Это сработало так, как мне было нужно. Спасибо, и документация была оценена.
2. Рад, что смог помочь. Я только что заметил, что один из моих комментариев был неправильным, и исправил его … немного об одном файле.