2014-09-22 52 views
1

這是一個用於類分配的組件,所以如果我無法根據需要深入討論,我表示歉意。總之,我需要編寫一個將所有相同文件(意思是具有不同文件名的相同內容的文件)分組的Python函數。對它們進行分組的目的是最終創建一個類型爲{string:list}的字典,其中列表是相同文件的組,並且鍵(字符串)只是按字母順序排序時組中的第一個條目。我們給了一個文件目錄。Python:查找完全相同的文件並對它們進行分組

到目前爲止,我有一個程序使用glob迭代每個文件,我也使用filecmp.cmp(file1,file2)來查找相同的文件。我所苦苦掙扎的是成功比較可達1000個文件的邏輯。我敢肯定有一個更pythonic的方式來完成這項任務,而不是比較file1到file2,file1到file3等。

總之,我知道如何遍歷文件列表,我知道如何創建一旦我有我的相同的文件組的一個字典...我只是有點失去了如何有效地獲得文件組。

示例實現 有7個文件:A,AA,AAA,B,BB,C,D文件A,AA和AAA是相同的B和BB是相同的,而C和d是唯一的。我的最終字典應該是:

{'A':[A,AA,AAA],'B':[B,BB],'C':[C],'D':[D]}

預先感謝您的時間!

回答

3

我建議你從每個文件的內容計算一個「散列」。創建一個字典,其中的鍵是哈希值,並且這些值是文件名列表。

Python hashlib模塊有多個可以使用的散列算法。我建議SHA-1或MD-5。

這兩個不相同的文件非常不可能具有相同的散列值。如果你想絕對確定,你可以遍歷一個文件列表並比較實際的文件值,以確保它們確實相同。

您可以使用defaultdict使這個更簡單:How does collections.defaultdict work?

這僅僅是未經測試的僞代碼,但這樣做:

from collections import defaultdict 
import hashlib 

h = defaultdict(list) 

for filename in list_of_files_in_directory: 
    with open(filename, "r") as f: 
     data = f.read() 
    fhash = hashlib.sha1(data).hexdigest() 
    h[fhash].append(filename) 

# h now contains a key for each unique file contents hash, and a list of filenames for each key 

你的字典可以只使用二進制散列數據作爲密鑰,但使用字符串值更方便。方法函數.hexdigest()爲您提供了一個表示散列爲十六進制數字的字符串。

編輯:在評論中,@parchment建議使用os.stat()來獲取文件大小,並且只有在有多個文件具有相同大小時才計算文件哈希值。這是加速找到相同文件的一個很好的方法;如果您只有一個文件具有特定的長度,則您知道它不能與任何其他文件相同。如果文件很大,計算哈希值可能會很慢。

但我會建議先編寫簡單的哈希代碼,並讓它工作,然後如果您有時間嘗試重寫它來檢查文件大小。檢查文件大小,然後有時還會散列文件的代碼會更復雜,因此更難以正確使用。

了我的頭頂部,這裏是我會怎樣改寫使用文件大小:

請叫done空列表。這是存儲輸出的地方(內容相​​同的文件名列表)。

將字典映射文件長度爲文件名列表。如上所示,您可以使用defaultdict

循環遍歷字典。每個值都是一個包含單個文件名的列表,只需將該值附加到done列表;唯一的長度意味着一個獨特的文件。每個值都是兩個或多個文件的列表,您現在需要計算散列值,並使用該散列值構建另一個字典映射散列值到文件列表。完成後,只需遍歷此字典中的所有值並將它們添加到done。基本上這部分與散列所有文件的解決方案是相同的代碼;只是現在你不需要散列每個文件,只是具有非唯一長度的文件。

+0

您可以先將文件大小與stat調用進行比較,然後使用相同大小對文件進行散列處理,以提高性能。散列1000個文件可能需要一段時間。 – parchment 2014-09-22 22:53:31

相關問題