Python:查找相同的文件并将它们分组

pur*_*doo 1 python file-io dictionary python-3.x

这是课堂作业的一个组成部分,因此如果我无法按照需要深入探讨,我深表歉意。

总而言之,我需要编写一个 python 函数,对所有相同的文件进行分组(即内容相同但文件名不同的文件)。对它们进行分组的目的是最终创建一个 {string: list} 类型的字典,其中列表是相同文件的组,而键(字符串)只是按字母顺序排序时组中的第一个条目。我们得到了一个文件目录。

到目前为止,我有一个使用 glob 迭代每个文件的程序,并且我还使用 filecmp.cmp(file1,file2) 来查找相同的文件。我正在努力解决的是成功比较最多 1000 个文件所需的逻辑。我确信有一种更 Pythonic 的方法来完成此任务,而不是比较 file1 与 file2、file1 与 file3 等。

总之,我知道如何迭代文件列表,并且一旦拥有相同文件组,我知道如何创建字典......我只是对如何有效获取文件组有点迷失。

示例实现 有 7 个文件:A、AA、AAA、B、BB、C、D。文件 A、AA 和 AAA 相同,B 和 BB 相同,而 C 和 D 唯一。我最终的字典应该是:

{'A':[A,AA,AAA],'B':[B,BB],'C':[C],'D':[D]}

在此先感谢您的时间!

ste*_*eha 5

我建议您根据每个文件的内容计算“哈希”。创建一个字典,其中键是哈希值,值是文件名列表。

Pythonhashlib模块有多种可以使用的哈希算法。我建议使用 SHA-1 或 MD-5。

两个不相同的文件具有相同哈希值的可能性非常非常小。如果您想绝对确定,您可以循环遍历文件列表并比较实际的文件值以确保它们确实相同。

您可以使用defaultdict使这变得更容易: Collections.defaultdict Difference with normal dict

这只是未经测试的伪代码,但请执行以下操作:

from collections import defaultdict
import hashlib

h = defaultdict(list)

for filename in list_of_files_in_directory:
    with open(filename, "rb") as f:
        data = f.read()
    fhash = hashlib.sha1(data).hexdigest()
    h[fhash].append(filename)

# h now contains a key for each unique file contents hash, and a list of filenames for each key
Run Code Online (Sandbox Code Playgroud)

您的字典可以仅使用二进制哈希数据作为键,但使用字符串值更方便。该.hexdigest()方法函数为您提供一个以十六进制数字表示哈希值的字符串。

编辑:在评论中,@parchment 建议使用os.stat()来获取文件大小,并且仅在存在多个具有相同大小的文件时才计算文件哈希。这是加快查找相同文件过程的绝佳方法;如果您只有一个具有特定长度的文件,您就知道它不能与任何其他文件相同。如果文件很大,计算哈希值可能会很慢。

但我建议先编写简单的哈希代码,然后让它工作,然后如果有时间尝试重写它以检查文件大小。检查文件大小,有时还对文件进行哈希处理的代码将更加复杂,因此更难以正确执行。

在我的脑海中,以下是我将如何重写以使用文件大小:

创建一个名为 的空列表done。这是您存储输出的位置(内容相同的文件名列表)。

创建一个字典将文件长度映射到文件名列表。您可以defaultdict按照上图所示使用。

循环字典。每个值都是包含单个文件名的列表,只需将该值附加到done列表中即可;唯一的长度意味着唯一的文件。每个值都是两个或多个文件的列表,您现在需要计算哈希值并构建另一个字典,将哈希值映射到具有该哈希值的文件列表。完成后,只需循环该字典中的所有值并将它们添加到done. 基本上这部分与散列所有文件的解决方案的代码相同;只是现在您不需要对每个文件进行哈希处理,只需对长度不唯一的文件进行哈希处理即可。

编辑 2023-11-24:将文件打开为“rb”以避免编码错误。