2010-09-02 3 views
14

Мне нужно создать хэш для папки, содержащей некоторые файлы. Я уже выполнил эту задачу для каждого из файлов, но я ищу способ создать один хэш для всех файлов в папке. Любые идеи, как это сделать?Создание хеша для папки

(конечно, я могу создать хеш для каждого файла и сцепить его в какой-то большой хэш, но это не так, как я люблю)

Спасибо заранее.

ответ

1

Объединить имена файлов и файлы в одну большую строку и хэш, или сделать хэширование в кусках для производительности.

Конечно, вы должны принять несколько вещей во внимание:

  • Вам нужно сортировать файлы по имени, так что вы не получите два разных хэши в случае, если файлы изменений порядка.
  • Используя этот метод, вы учитываете только имена файлов и содержимое. если имя файла не засчитывается, вы можете сортировать по контенту сначала, а затем хеш, если имеет значение больше атрибутов (ctime/mtime/hidden/archived ..), включите их в строку с заголовком.
+0

Спасибо за ваш ответ. Строка может быть очень большой, поэтому мне нужно будет разделить ее на куски, просто подумав, как сделать это правильно. –

+0

Я помню, что у хэшеров C# была функция, чтобы накормить их кусками, и, наконец, вы можете попросить получить окончательный хеш, не уверенный, что это за функции/классы. С их помощью вы можете сортировать свои входы так, как вам нравится в памяти, затем создавать файлы циклов и загружать куски в несколько сотен КБ и передавать их хэширу, так что вам не нужно много памяти, но все равно потребуется некоторое время для хэширования, от чего вы не можете избавиться. – aularon

1

Если у вас уже есть хеши для всех файлов, просто сортируйте хеши в алфавитном порядке, объедините их и снова хэш их, чтобы создать хэш uber.

7

Создать tarball файлов, hash tarball.

> tar cf hashes *.abc 
> md5sum hashes

Или хэш отдельных файлов и выход труб в хэш-команду.

> md5sum *.abc | md5sum

Edit: оба подхода выше, не сортировать файлы так может возвращать разные хэш для каждого вызова, в зависимости от того, как оболочка расширяется звездочками.

+0

+1 для творческого мышления – Paedow

+0

+1 Это на самом деле прямой подход :) –

+0

Это единственный ответ, который также учитывает * всякую метаинформацию, такую ​​как даты, права доступа, uids, guid, ... – itsafire

23

Это хеширует все файлы (относительные) пути и содержимое и корректно обрабатывает порядок файлов.

И это быстро - как 30 мс для каталога 4 МБ.

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

Очень приятно –

+0

Остерегайтесь соответствия FIPS, если вы когда-либо развертываете это на сервере с локальной политикой безопасности, которая обеспечивает соответствие FIPS. – SkeetJon

+0

@SkeetJon. Техника одинакова для любого криптографического алгоритма, поэтому вы можете просто заменить SHA для машин FIPS. –

9

Ответ Дунка хорошо работает; однако он не обрабатывает пустой каталог. Код ниже возвращает MD5 'd41d8cd98f00b204e9800998ecf8427e' (MD5 для потока длины длиной 0) для пустого каталога.

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' с. –

Смежные вопросы