Как создать функцию os.walk (), которая сравнивает папки и подпапки двух каталогов? - PullRequest
1 голос
/ 30 сентября 2019

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

import filecmp
import os

src=r"C:\Users\j2the\Documents\Test3"
dst=r"C:\Users\j2the\Documents\Test4"


comparison = filecmp.dircmp(dst, src)

for dirpath,dirnames,filenames in os.walk(src):
    for folders in dirnames:
        if folders in comparison.common_dirs:
            print(folders)
            src_folder=os.path.abspath(os.path.join(dirpath,folders))
            dst_folder=os.path.abspath(os.path.join(dst,folders))
            folder_comparison = filecmp.dircmp(dst_folder, src_folder)

            for dirpath1,dirnames1,filenames1 in os.walk(src_folder):

                for subfolders in dirnames1:
                    if subfolders in folder_comparison.common_dirs:
                        print(subfolders)
                        src_subfolder=os.path.abspath(os.path.join(dirpath1,subfolders))
                        dst_subfodler=os.path.abspath(os.path.join(dst_folder,subfolders))
                        subfolder_comparison=filecmp.dircmp(dst_subfodler,src_subfolder)

Это очень простой код. Однако этот код работает только с каталогами, которые имеют макс. 2 подпапки. Если бы я хотел проанализировать каталоги с большим количеством подпапок, мне пришлось бы добавить тонны вложенных циклов в мой код. Конечно, есть другой способ сделать это, верно? Я думал о создании цикла while, который будет проходить через каждую подпапку и сравнивать их, пока не останется подпапка, но я просто не мог понять, как это сделать. Любая помощь / вклад будет принята с благодарностью!

Ответы [ 2 ]

1 голос
/ 30 сентября 2019

Вам не нужно filecmp.dircmp. Вместо этого сделайте два вызова для os.walk с двумя каталогами, которые вы хотите сравнить, zip выходными данными двух генераторов и используйте пересечение наборов для двух подкаталогов из выходных данных, чтобы найти общие подкаталоги.

Обратите внимание, что ключом к выполнению рекурсивного обхода является выполнение замены на месте подкаталогов, возвращаемых обоими генераторами, так что для более глубокого обхода сохраняются только подкаталоги, общие для обоих текущих каталогов. и дальнейшие сравнения:

import os
for (root1, dirs1, _), (root2, dirs2, _) in zip(os.walk('dir1'), os.walk('dir2')):
    dirs1[:] = dirs2[:] = set(dirs1).intersection(dirs2)
    for common_dir in dirs1:
      print('Common sub-directory of {} and {}: {}'.format(root1, root2, common_dir))

Из документации os.walk:

Когда topdown равно True, вызывающая сторона может изменитьdirnames список на месте (возможно, с использованием del или назначением слайса), а walk() будет повторяться только в подкаталогах, имена которых остаются в dirnames;это может быть использовано для сокращения поиска ...

0 голосов
/ 30 сентября 2019

Это простой трюк, который работает (тестирование на Mac). Функция os.walk возвращает генератор дерева каталогов, который можно преобразовать в список. Однако из-за потенциально разных имен корневых каталогов я удалил первый элемент в каждом элементе списка.

Редактировать: сравнивает только структуру каталогов, а не содержимое.

res1 = [r[1:] for r in os.walk(src)]
res2 = [r[1:] for r in os.walk(dst)]

comparison = res1 == res2
...