2010-09-02 88 views
14

我需要爲包含一些文件的文件夾創建哈希。我已經爲每個文件完成了這項任務,但我正在尋找爲文件夾中的所有文件創建一個散列的方式。任何想法如何做到這一點?爲文件夾創建哈希

(當然我可以爲每個文件哈希,並將其拼接到一些大的哈希,但它不是一種方法,我喜歡)

在此先感謝。

回答

1

將文件名和文件內容連接在一個大字符串中並對其進行散列,或者對塊進行散列以獲得性能。

當然,你需要考慮幾件事情考慮:

  • 你需要按名稱排序文件,這樣你就不會得到兩個不同的哈希值的情況下,爲了文件的變化。
  • 使用此方法只考慮文件名和內容。如果文件名不算,你可以先按內容排序,然後再按散列,如果更多屬性(ctime/mtime/hidden/archived ..)很重要,請將它們包含在待處理的字符串中。
+0

感謝您的回覆。字符串可能非常大,所以我需要將它分成大塊,只是想如何正確地做到這一點。 – 2010-09-02 09:51:41

+0

我記得C#hashers有一個函數來爲它們提供塊,最後你可以要求獲得最終的哈希,不知道這些函數/類是什麼。有了它們,您可以按照自己喜歡的方式在內存中對輸入進行排序,然後循環文件並將塊加載到幾百KB中,並將其送入散列器,這樣您不需要太多內存,但仍然需要一些時間進行散列,這是你無法擺脫的。 – aularon 2010-09-02 10:11:50

1

如果你已經有了所有文件的散列,只需按字母順序對散列進行排序,連接它們並再次散列它們以創建一個超級散列。

7

創建文件tarball,散列tarball。

> tar cf hashes *.abc 
> md5sum hashes

或散列單個文件和管道輸出到哈希命令。

> md5sum *.abc | md5sum

編輯:這兩種方法上面沒有文件進行排序,以便可以返回不同的哈希每次調用,這取決於外殼是如何擴展星號。

+0

+1創造性思維 – Paedow 2013-10-14 20:10:56

+0

+1這實際上是直接的方法:) – 2014-01-02 17:11:36

+0

這是唯一的答案,也考慮到*所有*元信息如日期,訪問權限,用戶名,GUID,... – itsafire 2016-06-19 16:14:48

23

這散列所有文件(相對)路徑和內容,並正確處理文件排序。

它很快 - 就像一個4MB目錄30毫秒。

using System; 
using System.Text; 
using System.Security.Cryptography; 
using System.IO; 
using System.Linq; 

... 

public static string CreateMd5ForFolder(string path) 
{ 
    // assuming you want to include nested folders 
    var files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories) 
         .OrderBy(p => p).ToList(); 

    MD5 md5 = MD5.Create(); 

    for(int i = 0; i < files.Count; i++) 
    { 
     string file = files[i]; 

     // hash path 
     string relativePath = file.Substring(path.Length + 1); 
     byte[] pathBytes = Encoding.UTF8.GetBytes(relativePath.ToLower()); 
     md5.TransformBlock(pathBytes, 0, pathBytes.Length, pathBytes, 0); 

     // hash contents 
     byte[] contentBytes = File.ReadAllBytes(file); 
     if (i == files.Count - 1) 
      md5.TransformFinalBlock(contentBytes, 0, contentBytes.Length); 
     else 
      md5.TransformBlock(contentBytes, 0, contentBytes.Length, contentBytes, 0); 
    } 

    return BitConverter.ToString(md5.Hash).Replace("-", "").ToLower(); 
} 
+0

非常好的確 – 2013-05-17 15:13:46

+0

如果您使用本地安全策略將其部署到服務器並執行FIPS合規,請注意FIPS合規性 – SkeetJon 2015-06-08 12:21:52

+0

@SkeetJon對於任何加密算法,該技術都是相同的,因此您可以用SHA代替FIPS機器。 – 2015-12-30 23:25:24

9

Dunc的答案效果很好;但是,它不處理空目錄。下面的代碼爲空目錄返回MD5'd41d8cd98f00b204e9800998ecf8427e'(0長度字符流的MD5)。

public static string CreateDirectoryMd5(string srcPath) 
{ 
    var filePaths = Directory.GetFiles(srcPath, "*", SearchOption.AllDirectories).OrderBy(p => p).ToArray(); 

    using (var md5 = MD5.Create()) 
    { 
     foreach (var filePath in filePaths) 
     { 
      // hash path 
      byte[] pathBytes = Encoding.UTF8.GetBytes(filePath); 
      md5.TransformBlock(pathBytes, 0, pathBytes.Length, pathBytes, 0); 

      // hash contents 
      byte[] contentBytes = File.ReadAllBytes(filePath); 

      md5.TransformBlock(contentBytes, 0, contentBytes.Length, contentBytes, 0); 
     } 

     //Handles empty filePaths case 
     md5.TransformFinalBlock(new byte[0], 0, 0); 

     return BitConverter.ToString(md5.Hash).Replace("-", "").ToLower(); 
    } 
} 
+0

如果您使用此版本,則需要將'filePath'截斷爲相對路徑以創建'pathBytes'。 – 2017-12-28 14:29:28