Предложение 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
К счастью, у меня нет файлов / каталогов с символами новой строки в их именах, так что это не проблема в этой системе.