使用defaultdict重复文件查找器
我正在尝试使用不同的方法来根据文件内容识别重复文件,方法是循环访问文件夹AZ所在的顶级目录。 在文件夹AZ中,有一个额外的文件夹层以当前日期命名。 最后,在标有日期的文件夹中,有各种格式的数千到数百万(<300万)个文件。
使用下面的脚本,我能够在大约4个小时内处理大约800,000个文件。 然而,在一个大约1300万个文件的大型数据集上运行它时,它总是会破坏包含大约150万个文件的字母“I”。
鉴于我正在处理的数据大小,我正在考虑将内容直接输出到文本文件,然后将其导入到MySQL或类似的文件中以供进一步处理。 请让我知道,如果我正走向正确的轨道,或者如果您觉得下面的脚本的修改版本应该能够处理1300万个文件。
问题 - 如何修改下面的脚本来处理1300多万个文件?
错误追溯:
Traceback (most recent call last):
File "C:/Users/"user"/PycharmProjects/untitled/dups.py", line 28, in <module>
for subdir, dirs, files in os.walk(path):
File "C:Python34libos.py", line 379, in walk
yield from walk(new_path, topdown, onerror, followlinks)
File "C:Python34libos.py", line 372, in walk
nondirs.append(name)
MemoryError
我的代码:
import hashlib
import os
import datetime
from collections import defaultdict
def hash(filepath):
hash = hashlib.md5()
blockSize = 65536
with open(filepath, 'rb') as fpath:
block = fpath.read(blockSize)
while len(block) > 0:
hash.update(block)
block = fpath.read(blockSize)
return hash.hexdigest()
directory = "\pathtofiles"
directories = [name for name in os.listdir(directory) if os.path.isdir(os.path.join(directory, name))]
outFile = open("pathoutput.txt", "w", encoding='utf8')
for folder in directories:
sizeList = defaultdict(list)
path = directory + folder
print("Start time: " + str(datetime.datetime.now()))
print("Working on folder: " + folder)
# Walk through one level of directories
for subdir, dirs, files in os.walk(path):
for file in files:
filePath = os.path.join(subdir, file)
sizeList[os.stat(filePath).st_size].append(filePath)
print("Hashing " + str(len(sizeList)) + " Files")
## Hash remaining files
fileList = defaultdict(list)
for fileSize in sizeList.values():
if len(fileSize) > 1:
for dupSize in fileSize:
fileList[hash(dupSize)].append(dupSize)
## Write remaining hashed files to file
print("Writing Output")
for fileHash in fileList.values():
if len(fileHash) > 1:
for hashOut in fileHash:
outFile.write(hashOut + " ~ " + str(os.stat(hashOut).st_size) + 'n')
outFile.write('n')
outFile.close()
print("End time: " + str(datetime.datetime.now()))
免责声明:我不知道这是否是一种解决方案。
我看了你的代码,然后我意识到错误是由.walk
引起的。 现在的确,这可能是因为太多的信息被处理了(所以也许外部数据库会有所帮助,尽管增加的操作可能会阻碍你的速度)。 但.listdir
,处理大量文件时, .listdir
(由.walk
调用)真的很糟糕。 希望这可以在Python 3.5中解决,因为它实现了更好的scandir,所以如果你愿意*尝试最新的(我的意思是最新的,它是8天前发布的),这可能会有所帮助。
除此之外,您可以尝试追踪瓶颈,并收集垃圾,以便弄清楚。
*你也可以使用你的当前Python来安装它,但是它的乐趣在哪里?
链接地址: http://www.djcxy.com/p/69955.html