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

时间:2015-04-18 11:58:08

标签: python function sorting md5 os.walk

我正在编写一个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校验和的元素。

2 个答案:

答案 0 :(得分:1)

你快到了。关键是您必须反转字典的结构:为了轻松搜索具有相同校验和的文件,您可以使用MD5和作为,以及列表将校验和作为值的路径

{'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,它会让您的代码更具可读性

答案 1 :(得分:0)

您需要跟踪每个哈希的冲突文件名(即从哈希到具有该哈希的文件的文件名的映射)。最简单的方法是使用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)]