我尝试制作一个脚本,在文件夹中搜索双重文件并将其返回到这样的字典中 {filehash1:[dirfile1,dirfile2],filehash2:[dirfile3]} (dirfile1和dirfile2相同的文件名称/位置不同)
第一个代码:
import glob
import hashlib
def getallfolders(dir):
print dir+"*\\"
folders = glob.glob(dir+"*\\")
return folders
def getallfiles(dir):
folders = glob.glob(dir+"*.*")
return folders
def filehash(file):
BLOCKSIZE = 65536
hasher = hashlib.sha1()
with open(file, 'rb') as afile:
buf = afile.read(BLOCKSIZE)
while len(buf) > 0:
hasher.update(buf)
buf = afile.read(BLOCKSIZE)
return hasher.hexdigest()
def double_files(dir):
mil = {}
folders = getallfolders(dir)
for folder in folders:
mil.update(double_files(folder))
files = getallfiles(dir)
for file in files:
fhash = filehash(file)
if fhash in mil.keys():
mil[fhash] = mil[fhash] + [file]
else:
mil[fhash] = [file]
return mil
print double_files("E:\\not organised\\")
但如果我尝试运行它,它会崩溃并出现错误
IOError: [Errno 2] No such file or directory: file
它导致因为并非所有文件都用英文命名 所以我尝试修复它,现在代码看起来像这样:
# -*- coding: utf-8 -*-
import glob
import hashlib
import codecs
def getallfolders(dir):
print dir+"*\\"
folders = glob.glob(dir+"*\\")
return folders
def getallfiles(dir):
folders = glob.glob(dir+"*.*")
return folders
def filehash(file):
BLOCKSIZE = 65536
hasher = hashlib.sha1()
file = file.decode("utf8")
with codecs.open(file, "rb", encoding="utf8") as afile:
buf = afile.read(BLOCKSIZE)
while len(buf) > 0:
buf = buf.encode("ISO-8859-1")
hasher.update(buf)
buf = afile.read(BLOCKSIZE)
return hasher.hexdigest()
def double_files(dir):
mil = {}
folders = getallfolders(dir)
for folder in folders:
mil.update(double_files(folder))
files = getallfiles(dir)
for file in files:
fhash = filehash(file)
if fhash in mil.keys():
mil[fhash] = mil[fhash] + [file]
else:
mil[fhash] = [file]
return mil
print double_files("E:\\not organised\\")
我补充说
# -*- coding: utf-8 -*-
并改变
with open(file, 'rb')
到with open(file, encoding='utf-8')
但现在我得到了错误:
UnicodeDecodeError: 'utf8' codec can't decode byte .. in position ..: Tnvalid start byte
(...意思是它并不总是一样)
它在buf = afile.read(BLOCKSIZE)
行中很开心
我知道文件opend但是当我尝试使用read函数时它崩溃了。
我不知道如何解决它...
请帮忙。
答案 0 :(得分:0)
你似乎对编码很困惑......
# -*- coding: utf-8 -*-
仅适用于代码中的非ascii litteral 字符串。
file = file.decode("utf8")
将字符串file
(更好地命名为filename
)从utf-8解码为unicode。这仅适用于文件系统的编码(文件和文件夹名称)当然是utf-8(或者更确切地说,只要所有文件和文件夹名称都可解释为有效的utf-8)。当然,它对文件的内容没有太大作用。
codecs.open(file, "rb", encoding="utf8")
:这只有在您的文件内容实际上是一些utf-8编码的文本时才有意义,显然您正在阅读任何类型的二进制数据,因此如果您发现虚假的话,这并不奇怪编码错误。
buf.encode("ISO-8859-1")
:简单无用,hashlib.sha1()
可以使用utf-8。
总而言之: none 您的“修正”是有道理的。
回到问题的根源:
IOError:[Errno 2]没有这样的文件或目录:file 这是因为并非所有文件都用英文命名
我真的认为你在这里假设太多 - 如果你从浏览你的文件系统得到一个非ascii(不是“非英语”)文件名,那么你的文件系统应该支持这种非ascii编码(以及它是Windows,所以可能会有一些古怪的东西在这里,但我可以告诉你我永远在Linux和MacOS上都没有这样的问题)。在最糟糕的情况下,如果你肯定你的“非英语”(非ascii真的)文件名是utf8,你可以尝试使用 file = file.decode('utf-8')
来查看它是否更好但是仍然programming by accident
实际上由于你没有发布有效的追溯(使用完整的文件名),很难说你的原始代码到底出了什么问题,所以你最好的选择是切换回你的第一个实现并仔细阅读完整的追溯。然后,您可以使用交互式Python shell或the step debugger来进一步检查问题。
哦,是的:我假设你使用的是Python 2.x - Python 3处理的编码有点不同。
答案 1 :(得分:0)
所以在我阅读了你们所写的内容之后,我想到了我的探索并且这次真正修复了代码并且它工作正常 (发现我没注意到的字典的另一个问题) 工作代码:
import hashlib
from os import listdir
from os.path import isfile, join
import os
def getallfolders(dir):
folders = [d for d in os.listdir(dir) if os.path.isdir(os.path.join(dir, d))]
return folders
def getallfiles(dir):
folders = [f for f in listdir(dir) if isfile(join(dir, f))]
return folders
def filehash(file):
BLOCKSIZE = 65536
hasher = hashlib.sha1()
with open(file, "rb") as afile:
buf = afile.read(BLOCKSIZE)
while len(buf) > 0:
hasher.update(buf)
buf = afile.read(BLOCKSIZE)
return hasher.hexdigest()
def double_files(dir):
print dir
mil = {}
folders = getallfolders(dir)
for folder in folders:
newmil = double_files(dir + folder + "\\")
for i in newmil:
if i in mil.keys():
mil[i] = mil[i] + newmil[i]
else:
mil[i] = newmil[i]
files = getallfiles(dir)
for file in files:
fhash = filehash(dir + file)
if fhash in mil.keys():
mil[fhash] = mil[fhash] + [dir + file]
else:
mil[fhash] = [dir + file]
return mil
mil = double_files(u"E:\\not organised\\")
f = open('double_files.txt', 'w')
for i in mil:
if len(mil[i]) > 1:
for y in mil[i]:
f.write(y.encode('utf8')+"\n")
f.write("\n\n")
f.close()