shasum каталога в macos

shasum каталога в macos

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

В Linux и FreeBSD они shasumведут себя одинаково shasum <directory>, однако в MacOS они shasumвыдают мне хешитолько для файлов.

FreeBSD

$ shasum CONTENTS/
7f986e5e5289c59db1bba48df92ffe4707830aaa  CONTENTS/

Линукс

$ shasum CONTENTS/
7f986e5e5289c59db1bba48df92ffe4707830aaa  CONTENTS/

MacOS

$ shasum CONTENTS/
shasum: CONTENTS/: 

Как вычислить хеш каталога в MacOS?

ПОПЫТКА 1: Использование TAR с трубами

Попробовал использовать, но, похоже, эта опция tar не работает на MacOS.

tar cO CONTENTS/ | shasum
tar: Option -O is not permitted in mode -c
da39a3ee5e6b4b0d3255bfef95601890afd80709  -

ПОПЫТКА 2: Использование FIND/EXEC

Это было одинаково для MacOS и FreeBSD, но Linux вернул странный хеш

find CONTENTS -type f -exec shasum {} \; | sort -k 2 | shasum

Линукс

c2ddb9bc5f543e956f5cdcc76750cb78cc5f26f3

FreeBSD

3ac2a9d4e2fc5d2d2ec3c7f612e680990cc35824

MacOS

3ac2a9d4e2fc5d2d2ec3c7f612e680990cc35824

ДРУГИЕ ВЫВОДЫ ПО TAR

tarбыло бы отлично, так как он «архивирует» папку, и тогда я мог бы shasumэто сделать, однако порядок того, как tar«обходить» структуру папок,не согласованы между операционными системами. Как некоторые помощники отметили в комментариях, мне следует использовать одну и ту же версию tarво всех системах.

Просто пример: в системе 1 у меня такой порядок:

drwxr-xr-x  0 root   wheel       0 27 Jul 07:23 usr/
-rw-r--r--  0 root   wheel       0 27 Jul 07:25 usr/aaa
drwxr-xr-x  0 root   wheel       0 27 Jul 07:25 usr/f1/
-rw-r--r--  0 root   wheel       0 27 Jul 07:25 usr/f1/aaa
drwxr-xr-x  0 root   wheel       0 27 Jul 07:25 usr/f1/f0/
-rw-r--r--  0 root   wheel       0 27 Jul 07:25 usr/f1/f0/aaa
drwxr-xr-x  0 root   wheel       0 27 Jul 07:25 usr/f2/
-rw-r--r--  0 root   wheel       0 27 Jul 07:25 usr/f2/aaa
drwxr-xr-x  0 root   wheel       0 27 Jul 07:25 usr/f2/f1/
-rw-r--r--  0 root   wheel       0 27 Jul 07:25 usr/f2/f1/aaa
drwxr-xr-x  0 root   wheel       0 27 Jul 07:25 usr/f2/f1/f0/
-rw-r--r--  0 root   wheel       0 27 Jul 07:25 usr/f2/f1/f0/aaa
drwxr-xr-x  0 root   wheel       0 27 Jul 07:25 usr/f3/
-rw-r--r--  0 root   wheel       0 27 Jul 07:25 usr/f3/aaa
drwxr-xr-x  0 root   wheel       0 27 Jul 07:25 usr/f3/f2/
-rw-r--r--  0 root   wheel       0 27 Jul 07:25 usr/f3/f2/aaa
drwxr-xr-x  0 root   wheel       0 27 Jul 07:25 usr/f3/f2/f1/
-rw-r--r--  0 root   wheel       0 27 Jul 07:25 usr/f3/f2/f1/aaa

а в системе 2 у меня следующий порядок:

drwxr-xr-x  0 root   wheel       0 27 Jul 07:23 usr/
-rw-r--r--  0 root   wheel       0 27 Jul 07:25 usr/aaa
drwxr-xr-x  0 root   wheel       0 27 Jul 07:25 usr/f1/
drwxr-xr-x  0 root   wheel       0 27 Jul 07:25 usr/f2/
drwxr-xr-x  0 root   wheel       0 27 Jul 07:25 usr/f3/
-rw-r--r--  0 root   wheel       0 27 Jul 07:25 usr/f3/aaa
drwxr-xr-x  0 root   wheel       0 27 Jul 07:25 usr/f3/f2/
-rw-r--r--  0 root   wheel       0 27 Jul 07:25 usr/f3/f2/aaa
drwxr-xr-x  0 root   wheel       0 27 Jul 07:25 usr/f3/f2/f1/
-rw-r--r--  0 root   wheel       0 27 Jul 07:25 usr/f3/f2/f1/aaa
-rw-r--r--  0 root   wheel       0 27 Jul 07:25 usr/f2/aaa
drwxr-xr-x  0 root   wheel       0 27 Jul 07:25 usr/f2/f1/
-rw-r--r--  0 root   wheel       0 27 Jul 07:25 usr/f2/f1/aaa
drwxr-xr-x  0 root   wheel       0 27 Jul 07:25 usr/f2/f1/f0/
-rw-r--r--  0 root   wheel       0 27 Jul 07:25 usr/f2/f1/f0/aaa
-rw-r--r--  0 root   wheel       0 27 Jul 07:25 usr/f1/aaa
drwxr-xr-x  0 root   wheel       0 27 Jul 07:25 usr/f1/f0/
-rw-r--r--  0 root   wheel       0 27 Jul 07:25 usr/f1/f0/aaa

С tarточки зрения все хорошо, но из-за порядка получается shasumдругой хеш.

ЗАКЛЮЧЕНИЕ

shasumLinux и BSD единообразны в плане проверки хеша отдельного файла, но когда дело доходит до каталогов, единообразие наблюдается только в MacOS и FreeBSD, возможно, из-за способа сортировки файлов.

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

Использование tarдля создания временного файла и последующее выполнение shasumтакже оказалось несовместимым между Linux и BSD, возможно, из-за разницы в методе архивирования.

Я думаю, что единственный путь вперед — этоперепроектировать мое решение.

решение1

mtreeименно тот инструмент, который вам нужен.

Предполагать:

$ mkdir foo
$ date > foo/date1; sleep 3
$ date > foo/date2; sleep 3
$ date > foo/date3
$ grep . foo/*
foo/date1:Wed Jul 24 16:11:32 PDT 2019
foo/date2:Wed Jul 24 16:11:35 PDT 2019
foo/date3:Wed Jul 24 16:11:38 PDT 2019
$ find . -ls
7318841   0 drwxr-xr-x    3 admin    staff     102 Jul 24 16:11 .
7318847   0 drwxr-xr-x    5 admin    staff     170 Jul 24 16:11 ./foo
7318849   8 -rw-r--r--    1 admin    staff      29 Jul 24 16:11 ./foo/date1
7318851   8 -rw-r--r--    1 admin    staff      29 Jul 24 16:11 ./foo/date2
7318853   8 -rw-r--r--    1 admin    staff      29 Jul 24 16:11 ./foo/date3

Создайте ссылочный манифест каталога fooи сохраните его в foo.mtree:

$ mtree -c -K sha256digest -p foo > foo.mtree

Теперь идите и поработайте с любым файлом в этом каталоге.

$ touch foo/date3

Запустите его mtreeснова и передайте ему созданный ранее манифест, и mtreeон сообщит вам, что изменилось:

$ mtree -p foo < foo.mtree || echo fail
date3 changed
        modification time expected Wed Jul 24 16:11:38 2019 found Wed Jul 24 16:14:00 2019
fail

$ echo '$ date > foo/date2' >> bar
$ mtree -p foo < foo.mtree || echo fail
date2 changed
        modification time expected Wed Jul 24 16:11:35 2019 found Wed Jul 24 16:19:40 2019
        SHA-256 expected c76a568f08d98c2830f2fdfb42415c3ec15341b8741450d4bbd863f1d5c4c691 found ddcf8d07785bfe4d031a989339835dc3b8b44653019568dcee612c44fc8e2f70
date3 changed
        modification time expected Wed Jul 24 16:11:38 2019 found Wed Jul 24 16:14:00 2019
fail

Также будет сообщено о любых файлах, отсутствующих fooили добавленных с момента создания манифеста:

$ mv foo/date1 foo/date4
$ mtree -p foo < foo.mtree || echo fail
. changed
        modification time expected Wed Jul 24 16:11:38 2019 found Wed Jul 24 16:21:38 2019
date2 changed
        modification time expected Wed Jul 24 16:11:35 2019 found Wed Jul 24 16:19:40 2019
        SHA-256 expected c76a568f08d98c2830f2fdfb42415c3ec15341b8741450d4bbd863f1d5c4c691 found ddcf8d07785bfe4d031a989339835dc3b8b44653019568dcee612c44fc8e2f70
date3 changed
        modification time expected Wed Jul 24 16:11:38 2019 found Wed Jul 24 16:14:00 2019
date4 extra
./date1 missing
fail

решение2

Рмлинтсделаю то, что (я так думаю) ты хочешь.

Соответствующие пункты:

  • По умолчанию SHA не используется, но его можно использовать.
  • Его можно установить на MacOS с помощью homebrew.
  • По умолчанию он не вычисляет контрольную сумму для одного указанного каталога. Его можно заставить вычислять контрольные суммы для всех каталогов с заданной начальной точки, как способ поиска «дубликатов» каталогов ниже этой точки. Но в качестве побочного эффекта он также будет делать именно то, о чем вы, кажется, просите.
  • Это может оказаться излишним для того, что вы ищете, и вам может потребоваться некоторое время, чтобы определить наилучшие флаги опций для использования, но это довольно надежно.
  • Выяснение того, какие флаги использовать, может быть сложным. Получить контрольные суммы каталогов достаточно просто, но заставить егонетделать другие вещи, может быть сложно. (Хотя, если быть точным, он на самом деле ничего не изменяет. В лучшем случае он генерирует скрипт оболочки, который вы можете вручную запустить позже, чтобы изменить что-то, если это необходимо. Похоже, вам нужны выходные файлы JSON и/или CSV, которые дадут вам контрольную сумму каталога, которую вы ищете.)

Я использую rmlint в скрипте bash для поиска дубликатов каталогов. Вот команда, которая сделает минимально то, что вам нужно, и как можно меньше других:

rmlint "base/dir/to/start/from" --see-symlinks --hidden --algorithm=sha256 --types=none,duplicatedirs --no-backup -o csv:log.csv

Связанный контент