Shasum eines Verzeichnisses in macOS

Shasum eines Verzeichnisses in macOS

Ich schreibe ein Shell-Skript, das shasumüberprüft, ob sich der Inhalt eines Verzeichnisses geändert hat.

Unter Linux und FreeBSD shasumist das Verhalten gleich shasum <directory>, aber unter MacOS shasumbekomme ich Hashesnur für Dateien.

FreeBSD

$ shasum CONTENTS/
7f986e5e5289c59db1bba48df92ffe4707830aaa  CONTENTS/

Linux

$ shasum CONTENTS/
7f986e5e5289c59db1bba48df92ffe4707830aaa  CONTENTS/

Mac OS

$ shasum CONTENTS/
shasum: CONTENTS/: 

Wie kann ich den Hash eines Verzeichnisses in MacOS berechnen?

VERSUCH 1: TAR mit Pipes verwenden

Habe versucht, es zu verwenden, aber es scheint, dass diese Tar-Option unter MacOS nicht funktioniert.

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

VERSUCH 2: Verwenden von FIND/EXEC

Es war konsistent zwischen MacOS und FreeBSD, aber Linux gab einen seltsamen Hash zurück

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

Linux

c2ddb9bc5f543e956f5cdcc76750cb78cc5f26f3

FreeBSD

3ac2a9d4e2fc5d2d2ec3c7f612e680990cc35824

Mac OS

3ac2a9d4e2fc5d2d2ec3c7f612e680990cc35824

WEITERE ERKENNTNISSE ZU TAR

tarwäre ausgezeichnet, da es einen Ordner "archiviert" und dann könnte ich shasumes, jedoch ist die Reihenfolge, wie tar"durch die Ordnerstruktur gehen"nicht betriebssystemübergreifend konsistent. Wie einige Helfer in den Kommentaren erwähnt haben, sollte ich tarin allen Systemen die gleiche Version von verwenden.

Nur ein Beispiel, auf System 1 habe ich diese Reihenfolge:

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

und auf System 2 habe ich folgende Reihenfolge:

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

Vom tarStandpunkt aus ist alles gut, aber aufgrund der Reihenfolge shasumergibt sich ein anderer Hash.

ABSCHLUSS

shasumist unter Linux und BSDs konsistent, um einen einzelnen Datei-Hash zu prüfen, aber wenn es um Verzeichnisse geht, besteht die Konsistenz nur unter MacOS und FreeBSD, möglicherweise aufgrund der Art und Weise, wie die Dateien sortiert werden.

Wenn die Sortierung mit dem Befehl erzwungen wird find, wird Konsistenz nur unter FreeBSD und MacOS erreicht; diese Methode ist jedoch zeitaufwändig, da das Berechnen der Hashes für jede einzelne Datei und anschließend des gesamten Struktur-Hashes sehr viel Zeit in Anspruch nimmt.

Die Verwendung tarzum Erstellen einer temporären Datei und das anschließende Ausführen von shasumist zwischen Linux und BSDs ebenfalls inkonsistent, möglicherweise aufgrund unterschiedlicher Archivierungsmethoden.

Ich glaube, der einzige Weg nach vorn ist,meine Lösung neu gestalten.

Antwort1

mtreeist das gewünschte Werkzeug.

Vermuten:

$ 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

Erstellen Sie ein Referenzmanifest des Verzeichnisses foound speichern Sie es in foo.mtree:

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

Gehen Sie jetzt und bearbeiten Sie eine beliebige Datei in diesem Verzeichnis.

$ touch foo/date3

Führen Sie es mtreeerneut aus und übergeben Sie das Manifest, das Sie zuvor erstellt haben. mtreeSie erfahren dann, was sich geändert hat:

$ 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

Alle Dateien, die seit der Erstellung des Manifests fehlen foooder hinzugefügt wurden, werden ebenfalls gemeldet:

$ 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

Antwort2

Rmlintwird tun, was (glaube ich) Sie wollen.

Relevante Punkte:

  • Standardmäßig wird SHA nicht verwendet, dies kann aber angefordert werden.
  • Es kann über Homebrew auf MacOS installiert werden.
  • Standardmäßig berechnet es keine Prüfsumme für ein einzelnes angegebenes Verzeichnis. Es kann angewiesen werden, Prüfsummen für alle Verzeichnisse ab einem bestimmten Startpunkt zu berechnen, um „doppelte“ Verzeichnisse unterhalb dieses Punkts zu finden. Als Nebeneffekt wird es jedoch auch genau das tun, was Sie anscheinend verlangen.
  • Für das, was Sie suchen, ist das vielleicht übertrieben und es kann eine Weile dauern, bis Sie herausgefunden haben, welche Optionsflags sich am besten eignen, aber es ist recht robust.
  • Herauszufinden, welche Flags zu verwenden sind, kann schwierig sein. Verzeichnisprüfsummen zu erhalten ist einfach genug, aber es zu bekommennichtandere Dinge tun, kann schwierig sein. (Um es klarzustellen: Es ändert eigentlich nichts. Es generiert höchstens ein Shell-Skript, das Sie später manuell ausführen können, um Dinge bei Bedarf zu ändern. Was Sie anscheinend brauchen, sind die JSON- und/oder CSV-Ausgabedateien, die Ihnen die gewünschte Verzeichnisprüfsumme liefern.)

Ich verwende rmlint in einem Bash-Skript, um doppelte Verzeichnisse zu finden. Hier ist ein Befehl, der mindestens das tut, was Sie wollen, und so wenig anderes wie möglich:

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

verwandte Informationen