2010-09-02 93 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