我知道以前已经问过这个问题,并且已经看到了一些答案,但是这个问题更多地是关于我的代码和完成此任务的最佳方法。
我想扫描一个目录,并查看该目录中是否存在任何重复项(通过检查MD5哈希值)。以下是我的代码:
import sys import os import hashlib fileSliceLimitation = 5000000 #bytes # if the file is big, slice trick to avoid to load the whole file into RAM def getFileHashMD5(filename): retval = 0; filesize = os.path.getsize(filename) if filesize > fileSliceLimitation: with open(filename, 'rb') as fh: m = hashlib.md5() while True: data = fh.read(8192) if not data: break m.update(data) retval = m.hexdigest() else: retval = hashlib.md5(open(filename, 'rb').read()).hexdigest() return retval searchdirpath = raw_input("Type directory you wish to search: ") print "" print "" text_file = open('outPut.txt', 'w') for dirname, dirnames, filenames in os.walk(searchdirpath): # print path to all filenames. for filename in filenames: fullname = os.path.join(dirname, filename) h_md5 = getFileHashMD5 (fullname) print h_md5 + " " + fullname text_file.write("\n" + h_md5 + " " + fullname) # close txt file text_file.close() print "\n\n\nReading outPut:" text_file = open('outPut.txt', 'r') myListOfHashes = text_file.read() if h_md5 in myListOfHashes: print 'Match: ' + " " + fullname
这给了我以下输出:
Please type in directory you wish to search using above syntax: /Users/bubble/Desktop/aF 033808bb457f622b05096c2f7699857v /Users/bubble/Desktop/aF/.DS_Store 409d8c1727960fddb7c8b915a76ebd35 /Users/bubble/Desktop/aF/script copy.py 409d8c1727960fddb7c8b915a76ebd25 /Users/bubble/Desktop/aF/script.py e9289295caefef66eaf3a4dffc4fe11c /Users/bubble/Desktop/aF/simpsons.mov Reading outPut: Match: /Users/bubble/Desktop/aF/simpsons.mov
我的想法是:
1)扫描目录2)将MD5哈希+文件名写入文本文件3)以只读方式打开文本文件4)再次扫描目录并检查文本文件…
我看到这不是一个好方法,而且行不通。“匹配”仅打印出最后处理的文件。
如何获得此脚本以实际查找重复项?有人可以告诉我一种更好/更轻松的方法来完成此任务。
非常感谢您的帮助。抱歉,这是一个很长的帖子。
识别重复项的显而易见的工具是哈希表。除非您使用 大量 文件,否则可以执行以下操作:
from collections import defaultdict file_dict = defaultdict(list) for filename in files: file_dict[get_file_hash(filename)].append(filename)
在此过程结束时,file_dict将包含每个唯一哈希的列表;当两个文件具有相同的哈希时,它们都将出现在该哈希的列表中。然后过滤字典以查找长度超过1的值列表,并比较文件以确保它们相同- 如下所示:
file_dict
for duplicates in file_dict.values(): # file_dict.itervalues() in Python 2 if len(duplicates) > 1: # double-check reported duplicates and generate output
或这个:
duplicates = [files for files in file_dict.values() if len(files) > 1]
get_file_hash可以使用MD5;或者它可以像Ramchandra Apte在上面的注释中建议的那样简单地获取文件的开头和结尾字节;或者它可以像上面评论中建议的那样简单地使用文件大小。不过,后两种策略中的每一种都更有可能产生误报。您可以将它们组合以减少误报率。
get_file_hash
如果你有一个工作 非常 大量的文件,你可以使用一个更复杂的数据结构像一个布隆过滤器。