我知道之前已经问过这个问题,我已经看到了一些答案,但这个问题更多的是关于我的代码和完成这项任务的最佳方法.
我想扫描一个目录,看看该目录中是否有任何重复项(通过检查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)扫描目录AGAIN并检查文本文件…
我发现这不是一个很好的方法,它不起作用. ‘match’只打印出最后处理的文件.
如何让这个脚本实际找到重复?有人能告诉我更好/更简单的方法来完成这项任务.
非常感谢您的帮助.对不起,这是一篇很长的帖子.
解决方法:
用于识别重复项的明显工具是哈希表.除非您使用大量文件,否则您可以执行以下操作:
from collections import defaultdict
file_dict = defaultdict(list)
for filename in files:
file_dict[get_file_hash(filename)].append(filename)
在此过程结束时,file_dict将包含每个唯一哈希的列表;当两个文件具有相同的哈希时,它们都将出现在该哈希的列表中.然后过滤dict,查找长于1的值列表,并比较文件以确保它们是相同的 – 如下所示:
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可以使用MD5s;或者它可以简单地获取文件的第一个和最后一个字节,正如Ramchandra Apte在上面的评论中所建议的那样;或者它可以简单地使用文件大小作为上面评论中提出的tdelaney.后两种策略中的每一种都更有可能产生误报.您可以将它们组合起来以降低误报率.
如果您正在使用大量文件,则可以使用更复杂的数据结构,如Bloom Filter.