Правильный путь зависит от того, почему вы спрашиваете:
Вариант 1. Сравнение только данных
Если вам просто нужен хеш содержимого файла дерева, это поможет:
$ find -s somedir -type f -exec md5sum {} \; | md5sum
Это сначала суммирует все содержимое файла индивидуально, в предсказуемом порядке, затем передает этот список имен файлов и хэшей MD5 для хеширования, давая единственное значение, которое изменяется только при изменении содержимого одного из файлов в дереве.
К сожалению, find -s
работает только с BSD find (1), используемым в macOS, 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
расчетам «s.
У этой версии команды есть недостаток, заключающийся в том, что она может запутаться, если у вас есть какие-либо имена файлов с символами новой строки в них, потому что она будет выглядеть как несколько строк в sort
вызове. find -s
Вариант не имеет этой проблемы, так как обход дерева и сортировка происходит в течение одной и той же программы, find
.
В любом случае сортировка необходима, чтобы избежать ложных срабатываний: наиболее распространенные файловые системы Unix / Linux не поддерживают списки каталогов в стабильном, предсказуемом порядке. Вы можете не осознавать этого, используя ls
и тому подобное, которое молча сортирует содержимое каталога для вас. find
без -s
или sort
вызов собирается распечатать файлы в любом порядке, в котором их возвращает базовая файловая система, что приведет к тому, что эта команда выдаст измененное значение хеш-функции, если порядок файлов, переданных ей как входные, изменится
Возможно, вам придется изменить md5sum
команды md5
или некоторые другие хэш-функции. Если вы выбираете другую хеш-функцию и вам нужна вторая форма команды для вашей системы, вам может потребоваться настроить sort
команду соответствующим образом. Еще одна ловушка заключается в том, что некоторые программы суммирования данных вообще не записывают имя файла, основным примером является старая sum
программа Unix .
Этот метод несколько неэффективен, вызывая md5sum
N + 1 раз, где N - количество файлов в дереве, но это необходимая стоимость, чтобы избежать хэширования метаданных файла и каталога.
Вариант 2: сравнить данные и метаданные
Если вам необходимо определить, что изменилось что- либо в дереве, а не только содержимое файла, попросите tar
упаковать содержимое каталога для вас, а затем отправьте его по адресу md5sum
:
$ tar -cf - somedir | md5sum
Поскольку tar
он также определяет права доступа к файлам, владельца и т. Д., Он также обнаруживает изменения этих вещей, а не только изменения содержимого файла.
Этот метод значительно быстрее, так как он делает только один проход по дереву и запускает хэш-программу только один раз.
Как и в случае find
описанного выше метода based, tar
происходит обработка имен файлов в том порядке, в котором их возвращает базовая файловая система. Вполне может быть, что в вашем приложении вы можете быть уверены, что этого не произойдет. Я могу придумать, по крайней мере, три различных модели использования, где это может иметь место. (Я не собираюсь перечислять их, потому что мы попадаем на неопределенную область поведения. Здесь каждая файловая система может отличаться, даже от одной версии ОС к другой.)
Если вы обнаружите, что получаете ложные срабатывания, я бы рекомендовал find | cpio
выбрать вариант ответа Жиля .
find .
вместоfind somedir
. Таким образом, имена файлов совпадают, когда указываются разные пути; это может быть сложно :-)