我正在尝试编写一个Python脚本,它将获取目录中所有文件的md5sum(在Linux中)。我相信我已经在下面的代码中完成了。
我希望能够运行它以确保目录中没有文件发生更改,并且没有添加任何文件进行删除。
问题是我是否对目录中的文件进行了更改,然后将其更改回来。我从运行下面的函数得到了不同的结果。 (即使我更改了修改后的文件。
任何人都可以解释这个。如果你能想到一个解决方法,请告诉我?
def get_dir_md5(dir_path):
"""Build a tar file of the directory and return its md5 sum"""
temp_tar_path = 'tests.tar'
t = tarfile.TarFile(temp_tar_path,mode='w')
t.add(dir_path)
t.close()
m = hashlib.md5()
m.update(open(temp_tar_path,'rb').read())
ret_str = m.hexdigest()
#delete tar file
os.remove(temp_tar_path)
return ret_str
修改 正如这些优秀的人已经回答,看起来像tar包括标题信息,如修改日期。使用zip工作会有什么不同或其他格式吗?
还有其他的解决方法吗?
答案 0 :(得分:8)
正如其他提到的答案,即使由于tar元数据更改或文件顺序更改而导致内容相同,两个tar文件也可能不同。您应该直接对文件数据运行校验和,对目录列表进行排序以确保它们始终处于相同的顺序。如果要在校验和中包含一些元数据,请手动包含它。
使用os.walk
的未经测试的示例:
import os
import os.path
def get_dir_md5(dir_root):
"""Build a tar file of the directory and return its md5 sum"""
hash = hashlib.md5()
for dirpath, dirnames, filenames in os.walk(dir_root, topdown=True):
dirnames.sort(key=os.path.normcase)
filenames.sort(key=os.path.normcase)
for filename in filenames:
filepath = os.path.join(dirpath, filename)
# If some metadata is required, add it to the checksum
# 1) filename (good idea)
# hash.update(os.path.normcase(os.path.relpath(filepath, dir_root))
# 2) mtime (possibly a bad idea)
# st = os.stat(filepath)
# hash.update(struct.pack('d', st.st_mtime))
# 3) size (good idea perhaps)
# hash.update(bytes(st.st_size))
f = open(filepath, 'rb')
for chunk in iter(lambda: f.read(65536), b''):
hash.update(chunk)
return hash.hexdigest()
答案 1 :(得分:7)
TAR文件头包含文件修改时间的字段;更改文件的行为,即使稍后更改了该更改,也意味着TAR文件头将不同,从而导致不同的哈希值。
答案 2 :(得分:3)
您无需让TAR文件按照您的建议行事。
以下是您的解决方法算法:
单个结果签名将是您正在寻找的。
哎呀,你甚至不需要Python。你可以这样做:
find /path/to/dir/ -type f -name *.py -exec md5sum {} + | awk '{print $1}'\
| sort | md5sum
答案 3 :(得分:1)
tar
个文件包含超出实际文件内容的元数据,例如文件访问时间,修改时间等。即使文件内容没有改变,tar
文件实际上也会有所不同。