Для каталога переименуйте файл в подкаталоге с именем подкаталога старое имя файла в новый каталог

#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. Рад, что смог помочь. Я только что заметил, что один из моих комментариев был неправильным, и исправил его … немного об одном файле.