如何创建os.walk()函数来比较两个目录的文件夹和子文件夹?

问题描述 投票:0回答:3

这是我的问题:假设我要创建一个文件同步功能,该功能可以遍历两个相似目录的所有文件夹和子文件夹,并检测这两个目录的所有公用文件夹/子文件夹。我通过组合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循环,该循环将遍历每个子文件夹并进行比较,直到没有子文件夹为止,但是我根本不知道该怎么做。任何帮助/输入将不胜感激!

python for-loop os.walk file-comparison
3个回答
0
投票

我认为您不需要使用os.walk

如果只想进行布尔比较(如果目录树相等并且处理时没有错误),则可以执行以下操作:

def compare_dirs(dst, src):
    """compares directory trees"""
    comparison = filecmp.dircmp(dst, src)
    if len(comparison.left_only) > 0 or len(comparison.right_only) > 0 or len(comparison.funny_files) > 0:
        return False
    (_, mismatched, error) = filecmp.cmpfiles(dst, src, comparison.common_files, shallow=False)
    if len(mismatched) > 0 or len(error) > 0:
        return False
    for common in comparison.common_dirs:
        check1 = os.path.join(dst, common)
        check2 = os.path.join(src, common)
        if not compare_dirs(check1, check2): # recursion to check all files common between the two
            return False
    return True

这将递归比较文件,不仅是名称,还包括内容。或者,您可以在每个步骤中返回变量而不是布尔值,以查看差异。


0
投票

这是一个有效的简单技巧(在Mac上进行测试)。 os.walk函数返回目录树的生成器,可以将其生成一个列表。但是,由于根目录的名称可能不同,我删除了每个列表项中的第一个元素。

编辑:这仅比较目录结构而不是目录。

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

comparison = res1 == res2

0
投票

您不需要filecmp.dircmp。相反,使用要比较的两个目录对os.walk进行两次调用,zip两个生成器的输出,并在输出的两个子目录上使用set相交以找到公共子目录。

注意,进行递归遍历的关键是对两个生成器返回的子目录进行就地替换,以便仅保留两个当前目录所共有的子目录,以进行更深层次的遍历和进一步的遍历。比较:

import os
for (root1, dirs1, files1), (root2, dirs2, files2) in zip(os.walk('dir1'), os.walk('dir2')):
    dirs1[:] = dirs2[:] = set(dirs1).intersection(dirs2)
    for common_dir in dirs1:
      print(common_dir)

演示:https://repl.it/repls/VigorousWorseGravity

摘自os.walk的文档:

os.walktopdown时,呼叫者可以就地修改True列表(也许使用dirnames或切片分配),并且del仅会递归进入名称保留在walk()中的子目录;这可以是用于修剪搜索...

© www.soinside.com 2019 - 2024. All rights reserved.