Python3:基于文件内容递归比较两个目录

时间:2019-02-11 10:34:14

标签: python-3.x file stat

我有两个目录,其中包含一堆文件和子文件夹。 我想检查两个目录中的文件内容是否相同(忽略文件名)。子文件夹的结构也应该相同。

我查看了filecmp.dircmp,但这无济于事,因为它没有考虑文件内容。 shallow=False中没有filecmp.dircmp()选项,请参见here

this答案中的解决方法也不起作用,因为它考虑了文件名。

进行比较的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

解决这个问题。经过较小的测试后,这似乎可行,尽管还需要更多。同样,这可能会非常长,具体取决于文件数量及其大小:

import filecmp
import os
from collections import defaultdict
from sys import argv

def compareDirs(d1,d2):
    files1 = defaultdict(set)
    files2 = defaultdict(set)
    subd1  = set()
    subd2  = set()
    for entry in os.scandir(d1):
        if entry.is_dir(): subd1.add(entry)
        else: files1[os.path.getsize(entry)].add(entry)
    #Collecting first to compare length since we are guessing no
    #match is more likely. Can compare files directly if this is
    # not true.
    for entry in os.scandir(d2):
        if entry.is_dir(): subd2.add(entry)
        else: files2[os.path.getsize(entry)].add(entry)

    #Structure not the same. Checking prior to content.
    if len(subd1) != len(subd2) or len(files1) != len(files2): return False

    for size in files2:
        for entry in files2[size]:
            for fname in files1[size]: #If size does not exist will go to else
                if filecmp.cmp(fname,entry,shallow=False): break
            else: return False
            files1[size].remove(fname)
            if not files1[size]: del files1[size]

    #Missed a file
    if files1: return False

    #This is enough since we checked lengths - if all sd2 are matched, sd1
    #will be accounted for.
    for sd1 in subd1:
        for sd2 in subd2:
            if compareDirs(sd1,sd2): break
        else: return False #Did not find a sub-directory
        subd2.remove(sd2)

    return True

print(compareDirs(argv[1],argv[2]))

递归地输入两个目录。在第一级比较文件-如果不匹配,则失败。然后尝试将第一个目录中的任何子目录与下一个目录中的任何子目录进行递归匹配,直到所有内容都被匹配。

这是最幼稚的解决方案。在一般情况下,可能遍历树并且仅匹配大小和结构是有利的。在那种情况下,该函数看起来很相似,只是我们比较了getsize而不是使用filecmp并保存了匹配的树结构,因此第二次运行会更快。

当然,如果有几个子目录具有完全相同的结构和大小,我们仍然需要比较所有匹配的可能性。