7

我正在尝试编写一个 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 会以不同的方式或其他格式工作吗?

还有其他解决方法的想法吗?

4

4 回答 4

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()
于 2011-09-06T19:47:14.593 回答
7

TAR 文件头包含文件修改时间的字段;更改文件的行为,即使该更改后来被改回,也将意味着 TAR 文件头将不同,从而导致不同的哈希值。

于 2011-09-06T19:30:34.067 回答
3

您无需制作 TAR 文件即可执行您的建议。

这是您的解决方法算法:

  1. 遍历目录树;
  2. 取每个文件的md5签名;
  3. 对签名进行排序;
  4. 取单个文件的所有签名的文本字符串的 md5 签名。

单个生成的签名将是您正在寻找的。

哎呀,你甚至不需要 Python。你可以这样做:

find /path/to/dir/ -type f -name *.py -exec md5sum {} + | awk '{print $1}'\
| sort | md5sum
于 2011-09-06T19:38:30.640 回答
1

tar文件包含超出实际文件内容的元数据,例如文件访问时间、修改时间等。即使文件内容没有改变,tar文件实际上也会有所不同。

于 2011-09-06T19:31:35.510 回答