2011-09-06 82 views
7

我正在尝试编写一个Python脚本来获取目录中(Linux中)所有文件的md5sum。我相信我已经在下面的代码中完成了。确定在目录中是否添加,删除或修改了任何文件

我希望能够执行此操作以确保目录中的文件没有发生变化,并且没有文件被添加为删除。

问题是如果我对目录中的文件进行了更改,但之后又将其更改回来。运行下面的函数会得到不同的结果。 (虽然我改变了修改后的文件回

谁能解释这一点,让我知道,如果你能想到的一个变通

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 

编辑:。。? 由于这些罚款乡亲回答说,它看起来像焦油包括像修改日期标题信息。请问使用拉链的工作有什么不同或其他格式?

任何其他的想法变通?

回答

8

至于其他的答案中提到,二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() 
+2

很好的回答。我列出了同样的基本方法,但在代码中。尼斯。 –

7

TAR文件HEA ders包含文件修改时间的字段;更改文件的行为,即使该更改稍后被更改回来,也意味着TAR文件标头将会不同,从而导致不同的散列。

+0

感谢。我想没有选择告诉它不要包含文件头? – Greg

+1

即使可以,也不能保证TAR中文件的顺序必须一致。你可以做一些计算目录中每个文件的哈希值,然后根据这些值创建一个哈希值,这会严格地根据文件的内容告诉你它是否相同。 – Joe

1

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

3

你不需要让TAR文件做你的建议。

这里是你的解决方法的算法:

  1. 走在目录树;
  2. 取每个文件的md5签名;
  3. 排序签名;
  4. 获取单个文件所有签名的文本字符串的md5签名。

单个结果签名就是你要找的。

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

find /path/to/dir/ -type f -name *.py -exec md5sum {} + | awk '{print $1}'\ 
| sort | md5sum 
相关问题