Macos のディレクトリの shasum

Macos のディレクトリの shasum

shasumディレクトリの内容が変更されたかどうかを確認するためにを使用するシェル スクリプトを作成しています。

LinuxとFreeBSDでは、shasum私がそうした場合と同じ動作をしますshasum <directory>が、MacOSではshasumハッシュが表示されます。ファイルのみ

フリーBSD

$ shasum CONTENTS/
7f986e5e5289c59db1bba48df92ffe4707830aaa  CONTENTS/

リナックス

$ shasum CONTENTS/
7f986e5e5289c59db1bba48df92ffe4707830aaa  CONTENTS/

マックOS

$ 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

フリーBSD

3ac2a9d4e2fc5d2d2ec3c7f612e680990cc35824

マックOS

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異なるハッシュが生成されます。

結論

shasum個々のファイル ハッシュをチェックする点では Linux と BSD 間で一貫性がありますが、ディレクトリに関しては、ファイルのソート方法が原因で、MacOS と FreeBSD でのみ一貫性が保たれます。

コマンドを使用してソートを強制するとfind、一貫性は FreeBSD と MacOS でのみ得られますが、この方法は、すべてのファイルのハッシュを計算してから構造全体のハッシュを計算するのにかなりの時間がかかるため、時間がかかりすぎます。

を使用してtar一時ファイルを作成し、その後 を実行すると、shasumLinux と 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 を使用しませんが、使用するように指示することができます。
  • Homebrew 経由で MacOS にインストールできます。
  • デフォルトでは、指定された単一のディレクトリのチェックサムは計算されません。指定された開始点からすべてのディレクトリのチェックサムを計算するように指示すると、そのポイント以下の「重複」ディレクトリを見つけることができます。ただし、副作用として、まさにあなたが求めているようなことも実行されます。
  • これは、あなたが探しているものに対して過剰である可能性があり、使用する最適なオプション フラグを見つけるのにしばらく時間がかかるかもしれませんが、非常に堅牢です。
  • どのようなフラグを使うか決めるのは難しいかもしれません。ディレクトリのチェックサムを取得するのは簡単ですが、ない他のことを行うには、注意が必要です。(ただし、明確にしておくと、実際には何も変更されません。せいぜい、必要に応じて後で手動で実行して変更できるシェル スクリプトを生成します。必要なのは、探しているディレクトリ チェックサムを提供する JSON および/または CSV 出力ファイルのようです。)

私は bash スクリプトで rmlint を使用して、重複したディレクトリを検索します。以下は、必要なことだけを最低限実行し、それ以外のことはできるだけ行わないコマンドです。

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

関連情報