2011-09-06 31 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 
相關問題