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

StackOverflow https://stackoverflow.com/questions/1657232

  •  11-09-2019
  •  | 
  •  

Вопрос

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

Как лучше всего это сделать?

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

Это было полезно?

Решение

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

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

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

rsync -a ~/pybin/ ~/pybin2/

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

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

2bcf49a4d19ef9abd284311108d626f1  -

Другие советы

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

tar c dir | md5sum

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

предложение 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 withanewline» и двумя каталогами «named» и «withanewline», но вероятность того, что это произойдет, кажется очень маловероятной.Обычно это исправляют с помощью -print0 флаг для find но поскольку здесь происходят другие вещи, я вижу только решения, которые усложнят команду, чем она того стоит.

ПС:одна из моих систем использует ограниченный блок занятости 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

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

cat *.py | md5sum 

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

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)

GNU найти

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 $1}' | sort | md5sum

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

#!/bin/bash

if [ -z "$1" ] ; 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 $1

ls "$1" | while read line; do
  ecriv=`pwd`"/$1/"$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

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

find . -type f -print0 \ | xargs -r0 md5sum \ | grep -v ".env" \ | grep -v "vendor/autoload.php" \ | grep -v "vendor/composer/" \ | sort -d \ | md5sum

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top