Как вычислить контрольную сумму md5 каталога?

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

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

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

15 ответов


find /path/to/dir/ -type f -name "*.py" -exec md5sum {} + | awk '{print }' | sort | md5sum

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

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

rsync -a ~/pybin/ ~/pybin2/

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

на find...md5sum команда возвращает один и тот же вывод для обоих справочники.

2bcf49a4d19ef9abd284311108d626f1  -

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

tar c dir | md5sum

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


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

  • tar обрабатывает записи каталога в том порядке, в котором они хранятся в файловой системе, и нет возможности изменить этот порядок. Это эффективно может дать совершенно разные результаты, если у вас есть" один и тот же "каталог в разных местах, и я не знаю, как это исправить (tar не может" сортировать " свои входные файлы в определенном порядке).
  • я обычно забочусь о том, groupid и ownerid числа одинаковы, не обязательно, является ли строковое представление группы/владельца одинаковым. Это соответствует тому, что например rsync -a --delete делает: он синхронизирует практически все (минус xattrs и acls), но он будет синхронизировать владельца и группу на основе их ID, а не на строковое представление. Поэтому, если вы синхронизированы с другой системой, которая не обязательно имеет тех же пользователей / групп, вы должны добавить --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

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


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

find /path -type f | sort -u | xargs cat | md5sum

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


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

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

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

cat *.py | md5sum 

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

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

то же, что и выше, но только включая *.py files

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)

GNU find

find /path -type f -name "*.py" -exec md5sum "{}" +;

технически вам нужно только запустить ls -lR *.py | md5sum. Если вы не беспокоитесь о том, что кто-то изменит файлы и коснется их до их исходных дат и никогда не изменит размеры файлов, вывод из ls должен сообщить вам, если файл изменился. Мой unix-foo слаб, поэтому вам могут понадобиться дополнительные параметры командной строки, чтобы получить время создания и время модификации для печати. ls также сообщит вам, изменились ли разрешения на файлы (и я уверен, что есть переключатели для включения это выключено, если вам все равно).


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


используя md5deep:

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


У меня была та же проблема, поэтому я придумал этот скрипт, который просто перечисляет md5sums файлов в каталоге, и если он находит подкаталог, он снова запускается оттуда, для этого сценарий должен иметь возможность работать через текущий каталог или из подкаталога, если указанный аргумент передается в $1

#!/bin/bash

if [ -z "" ] ; then

# loop in current dir
ls | while read line; do
  ecriv=`pwd`"/"$line
if [ -f $ecriv ] ; then
    md5sum "$ecriv"
elif [ -d $ecriv ] ; then
    sh myScript "$line" # call this script again
fi

done


else # if a directory is specified in argument 

ls "" | while read line; do
  ecriv=`pwd`"//"$line

if [ -f $ecriv ] ; then
    md5sum "$ecriv"

elif [ -d $ecriv ] ; then
    sh myScript "$line"
fi

done


fi

Если вы хотите действительно независимы от атрибутов файловой системы и от битовых различий некоторых версий tar, вы можете использовать cpio:

cpio -i -e theDirname | md5sum

есть еще два решения:

создать:

du -csxb /path | md5sum > file

ls -alR -I dev -I run -I sys -I tmp -I proc /path | md5sum > /tmp/file

проверка:

du -csxb /path | md5sum -c file

ls -alR -I dev -I run -I sys -I tmp -I proc /path | md5sum -c /tmp/file