Как я могу вычислить контрольную сумму md5 каталога? - PullRequest
125 голосов
/ 01 ноября 2009

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

Каков наилучший способ сделать это?

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

Ответы [ 16 ]

159 голосов
/ 01 ноября 2009

Создайте файл архива tar на лету и отправьте его на md5sum:

tar c dir | md5sum

Это создает одну md5sum, которая должна быть уникальной для вашего файла и настройки подкаталога. На диске нет файлов.

144 голосов
/ 02 ноября 2009
find /path/to/dir/ -type f -name "*.py" -exec md5sum {} + | awk '{print $1}' | sort | md5sum

Команда find выводит список всех файлов, заканчивающихся на .py. Сумма md5 вычисляется для каждого файла .py. awk используется для выделения md5sums (игнорируя имена файлов, которые могут быть не уникальными). Суммы md5 отсортированы. Затем возвращается md5sum этого отсортированного списка.

Я проверил это, скопировав тестовый каталог:

rsync -a ~/pybin/ ~/pybin2/

Я переименовал некоторые файлы в ~ / pybin2.

Команда find...md5sum возвращает одинаковые выходные данные для обоих каталогов.

2bcf49a4d19ef9abd284311108d626f1  -
44 голосов
/ 20 октября 2011

Предложение ire_and_curses об использовании tar c <dir> имеет некоторые проблемы:

  • tar обрабатывает записи каталога в том порядке, в котором они хранятся в файловой системе, и изменить этот порядок невозможно. Это может эффективно привести к совершенно разным результатам, если у вас есть «один и тот же» каталог в разных местах, и я не знаю, как это исправить (tar не может «отсортировать» свои входные файлы в определенном порядке).
  • Меня обычно волнует, совпадают ли числа groupid и ownerid, не обязательно, совпадают ли строковые представления группы / владельца. Это соответствует тому, что делает, например, rsync -a --delete: он синхронизирует практически все (за исключением xattrs и acls), но синхронизирует владельца и группу на основе их идентификатора, а не строкового представления. Поэтому, если вы синхронизировались с другой системой, которая не обязательно имеет одинаковых пользователей / группы, вы должны добавить флаг --numeric-owner в tar
  • tar будет содержать имя файла каталога, который вы проверяете сам, просто о чем следует знать.

Пока нет решения для первой проблемы (или если вы не уверены, что это не влияет на вас), я бы не использовал этот подход.

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

Наконец, большинство предлагаемых решений не сортируются согласованно, поскольку параметры сортировки в разных системах могут быть разными.

Вот решение, которое я придумал:

dir=<mydir>; (find "$dir" -type f -exec md5sum {} +; find "$dir" -type d) | LC_ALL=C sort | md5sum

Примечания об этом решении:

  • LC_ALL=C - для обеспечения надежного порядка сортировки в системах
  • Это не делает различий между каталогом "named \ nwithanewline" и двумя каталогами "named" и "withanewline", но вероятность такого появления очень маловероятна. Обычно это исправляют с помощью флага -print0 для find, но, поскольку здесь происходят другие вещи, я вижу только решения, которые сделали бы команду более сложной, чем она того стоит.

PS: одна из моих систем использует ограниченный busybox find, который не поддерживает флаги -exec и -print0, а также добавляет «/» для обозначения каталогов, в то время как findutils find, похоже, не находит, поэтому для этой машины мне нужно запустить:

dir=<mydir>; (find "$dir" -type f | while read f; do md5sum "$f"; done; find "$dir" -type d | sed 's#/$##') | LC_ALL=C sort | md5sum

К счастью, у меня нет файлов / каталогов с символами новой строки в их именах, так что это не проблема в этой системе.

13 голосов
/ 10 апреля 2013

Если вы заботитесь только о файлах, а не о пустых каталогах, это прекрасно работает:

find /path -type f | sort -u | xargs cat | md5sum
10 голосов
/ 05 февраля 2013

Ради полноты есть md5deep (1) ; он не применяется напрямую из-за требования фильтра * .py, но должен работать вместе с find (1).

9 голосов
/ 08 апреля 2015

Решение, которое лучше всего сработало для меня:

find "$path" -type f -print0 | sort -z | xargs -r0 md5sum | md5sum

Причина, по которой это работает лучше всего для меня:

  1. обрабатывает имена файлов, содержащие пробелы
  2. Игнорирует метаданные файловой системы
  3. Определяет, был ли файл переименован

Вопросы с другими ответами:

Метаданные файловой системы не игнорируются для:

tar c - "$path" | md5sum

Не обрабатывает имена файлов, содержащие пробелы, и не определяет, был ли файл переименован:

find /path -type f | sort -u | xargs cat | md5sum
3 голосов
/ 02 марта 2015

Контрольная сумма всех файлов, включая содержимое и имена файлов

grep -ar -e . /your/dir | md5sum | cut -c-32

То же, что и выше, но только с * .py файлами

grep -ar -e . --include="*.py" /your/dir | md5sum | cut -c-32

Вы также можете перейти по символическим ссылкам, если хотите

grep -aR -e . /your/dir | md5sum | cut -c-32

Другие опции, которые вы можете использовать с grep

-s, --no-messages         suppress error messages
-D, --devices=ACTION      how to handle devices, FIFOs and sockets;
-Z, --null                print 0 byte after FILE name
-U, --binary              do not strip CR characters at EOL (MSDOS/Windows)
3 голосов
/ 01 ноября 2009

Если вы хотите, чтобы один md5sum охватывал весь каталог, я бы сделал что-то вроде

cat *.py | md5sum 
2 голосов
/ 18 июля 2014

Использование md5deep:

md5deep -r FOLDER | awk '{print $1}' | sort | md5sum

2 голосов
/ 20 октября 2012

Я использую HashCopy для этого. Он может генерировать и проверять MD5 и SHA для одного файла или каталога. Его можно загрузить с www.jdxsoftware.org.

...