Python:查找相同文件并对它们进行分组

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

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

总而言之,我需要编写一个 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]}

提前感谢您的宝贵时间!

python python-3.x file-io dictionary
1个回答
5
投票

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

Python

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

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

您可以使用

defaultdict
使这变得更加容易:Collections.defaultdict与普通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

你的字典可以只使用二进制哈希数据作为键,但使用字符串值更方便。

.hexdigest()
方法函数为您提供一个以十六进制数字表示哈希值的字符串。

编辑:在评论中,@parchment 建议使用

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

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

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

创建一个名为

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

将文件长度映射到文件名列表的字典。您可以使用

defaultdict
,如上所示。

循环字典。每个值都是包含单个文件名的列表,只需将该值附加到

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

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

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