搜索并打印具有相同 MD5 的文件

Search and print files that have the same MD5

我正在编写一个 Python 脚本来搜索文件夹(作为命令行参数传递)以查找具有相同 MD5 校验和(意味着这些文件相等)的文件并将它们打印在屏幕上。

我用了os.walk()函数扫描文件夹,写了一个计算MD5和的函数。但是现在我不知道如何搜索具有相同 MD5 校验和的文件。你能帮我解决这个问题吗?

#/usr/bin/env python3
import sys
import hashlib
import os
import operator
###############################################
def md5checksum (filepath):
    with open(filepath, "rb") as afile:
        m=hashlib.md5()
        data = afile.read()
        m.update(data)
        return m.hexdigest()
################################################
if __name__=="__main__":
    dir1 = sys.argv[1]
    info={}
    stampa=[]
    for path, dirname, filenames in os.walk(dir1):
        for filename in filenames:
            info[str(path)+filename]=md5checksum(str(path)+'/'+filename)

现在我想搜索并打印具有相同 MD5 校验和的元素。

您需要跟踪每个散列的冲突文件名(即从散列到具有该散列的文件的文件名的映射)。最简单的方法是使用 defaultdict.

以下代码为您提供了一个字典 hashes,其中包含 MD5 校验和作为键,以及包含具有该校验和的文件列表作为值。然后,您可以轻松地过滤具有多个项目的列表的值(即具有相同散列的两个或多个文件)。

#/usr/bin/env python3
import sys
import hashlib
import os
import operator
from collections import defaultdict
###############################################
def md5checksum (filepath):
    with open(filepath, "rb") as afile:
        m=hashlib.md5()
        data = afile.read()
        m.update(data)
    return m.hexdigest()
################################################
if __name__=="__main__":
    dir1 = sys.argv[1]
    info={}
    hashes = defaultdict(list)
    for path, dirname, filenames in os.walk(dir1):
        for filename in filenames:
            md5 = md5checksum(os.path.join(path, filename))
            info[str(path)+filename] = md5
            hashes[md5] += [os.path.join(path, filename)]

你快到了。关键是你必须反转字典的结构:为了方便地搜索具有相同校验和的文件,你可以使用 MD5 和作为 key,并且 具有该校验和作为值的路径列表

{'6d4840fa80a877c234895ba45229d939': ['./search.py'],
 '7dac6bd007fce17b0325a693fdb62c68': ['./foo/foo1/f.txt', './foo/foo1/f2.txt'],
 'e7b39e258d9b15300d1732bfce9d89bd': ['./foo/foo1/f3.txt']}

然后检查简单地归结为:特定校验和在其路径列表中是否有多个条目?如果是,则这些文件具有相同的校验和。

在这段代码中,我使用了一个默认为列表的 defaultdict,以避免必须检查校验和是否已经在字典中。

#!/usr/bin/env python3
from collections import defaultdict
import hashlib
import os
import sys


def md5checksum(filepath):
    with open(filepath, "rb") as afile:
        m = hashlib.md5()
        data = afile.read()
        m.update(data)
    return m.hexdigest()


def calculate_checksums(search_dir):
    checksums = defaultdict(list)

    for root, dirs, files in os.walk(search_dir):
        for filename in files:
            path = os.path.join(root, filename)
            checksum = md5checksum(path)
            checksums[checksum].append(path)
    return checksums


def display_equal_files(checksums):
    for checksum, paths in checksums.items():
        if len(paths) > 1:
            print("MD5 sum: {}".format(checksum))
            for path in paths:
                print("    {}".format(path))


if __name__ == "__main__":
    search_dir = sys.argv[1]
    checksums = calculate_checksums(search_dir)
    display_equal_files(checksums)

示例输出:

MD5 sum: 8863775ebac6399b538c852e5ee03559
    ./bar/bar.txt
    ./baz/bar2.txt
MD5 sum: 7dac6bd007fce17b0325a693fdb62c68
    ./foo/foo1/f.txt
    ./foo/foo1/f2.txt

几个注意事项:

  • 你的 shebang 是错误的。它应该以 #!/ 开头,而不是 #/
  • 您的 md5checksums() 函数中的缩进错误。缩进在 Python 中非常重要,请务必密切注意它。
  • 使用 os.path.join 加入文件路径。
  • 尝试遵循 PEP8 style guide,它使您的代码更具可读性