КАК ПОЛУЧИТЬ СУММУ MD5 СОДЕРЖИМОГО КАТАЛОГА В ВИДЕ ОДНОЙ СУММЫ?


Предыдущая | Следующая

Программа md5sum не предоставляет контрольные суммы для каталогов. Я хочу получить одну контрольную сумму MD5 для всего содержимого каталога, включая файлы в подкаталогах. То есть, одна комбинированная контрольная сумма была сделана из всех файлов. Есть ли способ сделать это?

 
 

 

 

 
  • Что такое «контрольная сумма» и как ее использовать из оболочки?
  • Разделение двух каталогов рекурсивно на основе контрольных сумм?
  • Обновление Kali Linux не работает на Metasploit с ошибкой контрольной суммы хэша
  • Как отдельно проверять каждый «блок» большого файла
  • различные утилиты контрольных сумм предшествуют хешу с обратной косой чертой
  • Репозиторий пакета FreeBSD - как выполнить ручную проверку подписи?
  • как сделать контрольную сумму в папке в Solaris
  • Медленный

12 Solutions collect form web for “Как получить сумму MD5 содержимого каталога в виде одной суммы?”

Правильный путь зависит именно от того, почему вы спрашиваете:

Вариант 1: Сравнить только данные

Если вам просто нужен хэш содержимого файла дерева, это будет делать трюк:

$ find -s somedir -type f -exec md5sum {} \; | md5sum 

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

К сожалению, find -s работает только с BSD find (1), используемым в Mac OS X, FreeBSD, NetBSD и OpenBSD. Чтобы получить что-то сравнимое по системе с GNU или SUS find (1), вам нужно что-то немного уродливое:

 $ find somedir -type f -exec md5sum {} \; | sort -k 2 | md5sum 

Мы заменили find -s на вызов sort . Бит -k 2 сообщает ему пропустить хэш MD5, поэтому он сортирует имена файлов, которые находятся в поле 2 по конец строки, по подсчету sort .

В этой версии команды есть слабость, которая заключается в том, что она может смущаться, если у вас есть имена файлов с новыми строками в них, потому что это будет выглядеть как несколько строк для вызова sort . Вариант find -s не имеет этой проблемы, потому что обход дерева и сортировка происходят в одной программе, find .

В любом случае сортировка необходима, чтобы избежать ложных срабатываний. * ix файловые системы не поддерживают списки каталогов в стабильном, предсказуемом порядке; вы можете не понимать этого, используя ls и т. д., которые молча сортируют содержимое каталога для вас. find без -s или вызов sort собираются распечатывать файлы в любом порядке, который возвращает их базовая файловая система, что может привести к тому, что эта команда даст измененное хеш-значение, когда все, что было изменено, – это порядок файлов в каталоге.

Возможно, вам придется изменить команды md5sum на md5 или другую хэш-функцию. Если вы выберете другую хеш-функцию и вам понадобится вторая форма команды для вашей системы, вам может потребоваться настроить команду sort если ее выходная строка не имеет хеша, за которой следует имя файла, разделенное пробелом. Например, вы не можете использовать старую программу для Unix для этого, потому что ее вывод не включает имя файла.

Этот метод несколько неэффективен, вызывая md5sum N + 1 раз, где N – количество файлов в дереве, но это необходимая стоимость, чтобы избежать метаданных файлов хеширования и каталога.

Вариант 2. Сравнение данных и метаданных

Если вам нужно обнаружить, что что- либо в дереве изменилось, а не только содержимое файла, попросите tar упаковать содержимое каталога для вас, а затем отправьте его в md5sum :

 $ tar -cf - somedir | md5sum 

Поскольку tar также видит права доступа к файлам, право собственности и т. Д., Это также обнаружит изменения в этих вещах, а не только изменения содержимого файла.

Этот метод значительно быстрее, так как он делает только один проход по дереву и запускает хеш-программу только один раз.

Как и вышеописанный метод find , tar будет обрабатывать имена файлов в том порядке, в котором их возвращает базовая файловая система. Вполне возможно, что в вашем приложении вы можете быть уверены, что это не произойдет. Я могу придумать, по крайней мере, три разных шаблона использования, где это может произойти. (Я не буду перечислять их, потому что мы попадаем в неопределенную область поведения. Каждая файловая система может быть различной здесь, даже с одной версии ОС до следующей).

Если вы обнаружите, что получаете ложные срабатывания, я бы рекомендовал пойти с find | cpio find | cpio в ответе Жиля.

Контрольная сумма должна быть детерминированным и недвусмысленным представлением файлов в виде строки. Детерминистский означает, что если вы поместите одинаковые файлы в одно и то же место, вы получите тот же результат. Однозначность означает, что два разных набора файлов имеют разные представления.

Данные и метаданные

Создание архива, содержащего файлы, является хорошим началом. Это недвусмысленное представление (очевидно, поскольку вы можете восстановить файлы, извлекая архив). Он может включать метаданные файлов, такие как даты и право собственности. Однако это еще не совсем верно: архив неоднозначен, поскольку его представление зависит от порядка хранения файлов и, если применимо, при сжатии.

Решение заключается в сортировке имен файлов перед их архивированием. Если имена ваших файлов не содержат символы новой строки, вы можете запустить find | sort find | sort чтобы их перечислить, и добавить их в архив в этом порядке. Позаботьтесь о том, чтобы архиватор не переписывался в справочники. Вот примеры с POSIX pax , GNU tar и cpio:

 find | LC_ALL=C sort | pax -w -d | md5sum find | LC_ALL=C sort | tar -cf - -T - --no-recursion | md5sum find | LC_ALL=C sort | cpio -o | md5sum 

Только имена и содержимое, низкотехнологичный способ

Если вы хотите только принять данные файла, а не метаданные, вы можете создать архив, содержащий только содержимое файла, но для этого нет стандартных инструментов. Вместо включения содержимого файла вы можете включить хэш файлов. Если имена файлов не содержат новых строк, и есть только обычные файлы и каталоги (без символических ссылок или специальных файлов), это довольно просто, но вам нужно позаботиться о нескольких вещах:

 { export LC_ALL=C; find -type f -exec wc -c {} \; | sort; echo; find -type f -exec md5sum {} + | sort; echo; find . -type d | sort; find . -type d | sort | md5sum; } | md5sum 

Мы включаем список каталогов в дополнение к списку контрольных сумм, так как в противном случае пустые каталоги будут невидимыми. Список файлов сортируется (в специфическом, воспроизводимом языке – благодаря Peter.O, чтобы напомнить мне об этом). echo разделяет две части (без этого вы можете создать несколько пустых каталогов, чье имя будет выглядеть как вывод md5sum который также может передаваться для обычных файлов). Мы также включаем список размеров файлов, чтобы избежать атак с расширением длины .

Кстати, MD5 устарел. Если это доступно, попробуйте использовать SHA-2 или, по крайней мере, SHA-1.

Имена и данные, поддерживающие новые строки в именах

Вот вариант кода выше, который опирается на инструменты GNU для разделения имен файлов с помощью нулевых байтов. Это позволяет именам файлов содержать новые строки. Утилиты дайджеста GNU цитируют специальные символы в их выводах, поэтому не будет неоднозначных строк новой строки.

 { export LC_ALL=C; du -0ab | sort -z; # file lengths, including directories (with length 0) echo | tr '\n' '\000'; # separator find -type f -exec sha256sum {} + | sort -z; # file hashes echo | tr '\n' '\000'; # separator echo "End of hashed data."; # End of input marker } | sha256sum 

Более надежный подход

Вот минимально проверенный скрипт Python, который создает хэш, описывающий иерархию файлов. Он берет каталоги и содержимое файла в учетные записи и игнорирует символические ссылки и другие файлы и возвращает фатальную ошибку, если какой-либо файл не может быть прочитан.

 #! /usr/bin/env python import hashlib, hmac, os, stat, sys ## Return the hash of the contents of the specified file, as a hex string def file_hash(name): f = open(name) h = hashlib.sha256() while True: buf = f.read(16384) if len(buf) == 0: break h.update(buf) f.close() return h.hexdigest() ## Traverse the specified path and update the hash with a description of its ## name and contents def traverse(h, path): rs = os.lstat(path) quoted_name = repr(path) if stat.S_ISDIR(rs.st_mode): h.update('dir ' + quoted_name + '\n') for entry in sorted(os.listdir(path)): traverse(h, os.path.join(path, entry)) elif stat.S_ISREG(rs.st_mode): h.update('reg ' + quoted_name + ' ') h.update(str(rs.st_size) + ' ') h.update(file_hash(path) + '\n') else: pass # silently symlinks and other special files h = hashlib.sha256() for root in sys.argv[1:]: traverse(h, root) h.update('end\n') print h.hexdigest() 

Посмотрите на md5deep . Некоторые из функций md5deep, которые могут вас заинтересовать:

Рекурсивная операция – md5deep способен рекурсивно проверять все дерево каталогов. То есть, вычислите MD5 для каждого файла в каталоге и для каждого файла в каждом подкаталоге.

Режим сравнения – md5deep может принимать список известных хэшей и сравнивать их с набором входных файлов. Программа может отображать либо те входные файлы, которые соответствуют списку известных хэшей, либо те, которые не совпадают.

Если ваша цель – найти различия между двумя каталогами, рассмотрите возможность использования diff.

Попробуй это:

 diff -qr dir1 dir2 

Вы можете хэшировать каждый файл рекурсивно, а затем хешировать полученный текст:

 > md5deep -r -l . | sort | md5sum d43417958e47758c6405b5098f151074 *- 

Требуется md5deep .

Содержание файла, исключая имена файлов

Мне нужна версия, которая проверяет только имена файлов, потому что содержимое находится в разных каталогах.

Эта версия (ответ Уоррена Янга) очень помогла, но моя версия md5sum выводит имя файла (относительно пути, из которого я запускал команду), и имена папок были разными, поэтому, несмотря на то, что контрольные суммы отдельных файлов совпадают, окончательная контрольная сумма не сделал.

Чтобы исправить это, в моем случае мне просто нужно было отключить имя файла из каждой строки вывода find (выберите только первое слово, разделенное пробелами с использованием cut ):

 find -s somedir -type f -exec md5sum {} \; | cut -d" " -f1 | md5sum 

Хорошая контрольная сумма дерева – это идентификатор дерева Git.

К сожалению, нет доступного автономного инструмента, который может это сделать (по крайней мере, я его не знаю), но если у вас есть Git, вы можете просто притворяться, что настроите новый репозиторий и добавьте файлы, которые хотите проверить в индексе.

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

решение :

 $ pip install checksumdir $ checksumdir -a md5 assets/js 981ac0bc890de594a9f2f40e00f13872 $ checksumdir -a sha1 assets/js 88cd20f115e31a1e1ae381f7291d0c8cd3b92fad 

работает быстрее и проще, а затем bash.

см. документ: https://pypi.python.org/pypi/checksumdir/1.0.5

nix-hash из диспетчера пакетов Nix

Команда nix-hash вычисляет криптографический хэш содержимого каждого пути и печатает его на стандартном выходе. По умолчанию он вычисляет хеш MD5, но также доступны другие алгоритмы хеширования. Хэш печатается в шестнадцатеричном формате.

Хэш вычисляется по сериализации каждого пути: дамп дерева файловой системы, внедренный в путь. Это позволяет хэшировать каталоги и символические ссылки, а также обычные файлы. Дамп находится в формате NAR, создаваемом nix-store – dump. Таким образом, путь nix-hash дает один и тот же криптографический хеш как путь nix-store –dump | md5sum.

Я использую этот мой фрагмент для умеренных объемов :

find . -xdev -type f -print0 | LC_COLLATE=C sort -z | xargs -0 cat | md5sum -

и этот для XXXL :

find . -xdev -type f -print0 | LC_COLLATE=C sort -z | xargs -0 tail -qc100 | md5sum -

Мне не нужны новые исполняемые файлы или неуклюжие решения, поэтому я беру их:

 #!/bin/sh # md5dir.sh by Camilo Martin, 2014-10-01. # Give this a parameter and it will calculate an md5 of the directory's contents. # It only takes into account file contents and paths relative to the directory's root. # This means that two dirs with different names and locations can hash equally. if [[ ! -d "$1" ]]; then echo "Usage: md5dir.sh <dir_name>" exit fi d="$(tr '\\' / <<< "$1" | tr -s / | sed 's-/$--')" c=$((${#d} + 35)) find "$d" -type f -exec md5sum {} \; | cut -c 1-33,$c- | sort | md5sum | cut -c 1-32 

Надеюсь, это поможет вам 🙂

Скрипт, который хорошо протестирован и поддерживает ряд операций, включая поиск дубликатов, сравнение данных и метаданных, показывающих дополнения, а также изменения и удаления, вам может понравиться Fingerprint .

Фингерпринт прямо сейчас не создает единую контрольную сумму для каталога, а файл транскрипции, который включает контрольные суммы для всех файлов в этом каталоге.

 fingerprint analyze 

Это создаст index.fingerprint в текущем каталоге, который включает контрольные суммы, имена файлов и размеры файлов. По умолчанию он использует как MD5 и SHA1.256 .

В будущем я надеюсь добавить поддержку Merkle Trees в Fingerprint, которая даст вам одну контрольную сумму верхнего уровня. Прямо сейчас вам нужно сохранить этот файл для проверки.