Überprüfen Sie, ob die (rekursive) Verzeichniskopie identisch ist

471
A. Donda

Manchmal muss ich große Datenmengen in einer Verzeichnisstruktur von einem Computer auf einen anderen kopieren / synchronisieren. Typische Programme, die ich für diesen Zweck verwende, sind rsync, syncthing oder seafile.

Um sich nicht ausschließlich auf die Korrektheit des Copy / Sync-Programms (oder der von mir gewählten Optionen) zu verlassen, generiere ich normalerweise eine Prüfsummen-Datei (using cfv) im übergeordneten Verzeichnis und kopiere / sync es mit den Daten, sodass ich später alles überprüfen kann ist auf dem Zielcomputer OK. Funktioniert beispielsweise cfvgut, um festzustellen, ob alle Dateien des Ursprungs sicher angekommen sind.

Eine Option, die ich vermisse, besteht jedoch darin, zu prüfen, ob sich in der Kopie Dateien befinden, die nicht im Original waren. Soweit ich das beurteilen kann, cfvgibt es keine Option, nach solchen "zusätzlichen" Dateien zu suchen. Die Lösung, auf die ich zurückgreife, besteht darin, eine neue Prüfsummendatei für die Kopie zu erstellen und sie mit dem Original zu vergleichen. Dies bedeutet jedoch, dass die Prüfsummen für jede Datei viermal berechnet werden müssen (Erstellen und Prüfen auf beiden Computern).

Gibt es eine bessere Lösung?

0

2 Antworten auf die Frage

2
Kamil Maciorowski

Die Berechnung von Prüfsummen sieht für mich nach einem Overkill aus, wenn Sie nur "zusätzliche" Dateien erkennen möchten. Sie müssen nicht die tatsächlichen Daten (Dateiinhalt) prüfen. Sie müssen Metadaten (vorhandene Pfade) überprüfen.

Um alle relativen Pfade nach innen zu bekommen /synced/dir, renne

(cd /synced/dir && find . | sort) > structure.txt 

Tun Sie es auf beiden Seiten, dann diffdie resultierenden Dateien. Beachten Sie, dass die Situation symmetrisch ist, so dass Sie auf jeder Seite "zusätzliche" sowie "fehlende" Dateien erkennen ("zusätzliche" ist hier gleichbedeutend mit "fehlendem" und umgekehrt).

Um "zusätzliche" Dateien auf der einen oder anderen Seite zu ignorieren, filtern Sie die diffAusgabe mit grep '^>'(bzw. grep '^<').

Wenn die beiden Verzeichnisse in einem einzigen System verfügbar sind (angehängt), kann diese Bash-Syntax nützlich sein:

diff <(cd /original/dir && find . | sort) <(cd /backup/dir && find . | sort) | grep '^>' 

Dies ist nicht völlig robust (z. B. Zeilenumbrüche in Dateinamen können die Logik zerstören). Behandeln Sie mein Beispiel eher als Konzeptnachweis. Der Punkt ist, dass Sie zusätzliche Dateien erkennen, ohne den Dateiinhalt überhaupt zu lesen.

Anmerkungen:

  • sortist erforderlich, da die beiden finds Einträge in unterschiedlicher Reihenfolge zurückgeben können, selbst wenn Verzeichnisse exakte Kopien sind;
  • Sole diffkann Verzeichnisse vergleichen, aber dieser Modus ist hier nicht hilfreich, da er versucht, den Inhalt entsprechender Dateien zu vergleichen. Dieses Verhalten möchten wir in erster Linie vermeiden.
Vielen Dank! Und es tut mir leid, dass ich das angenommen und dann nicht akzeptiert habe, aber Ihre Antwort inspirierte mich dazu, es noch schlanker zu machen. Sehen Sie meine Antwort. A. Donda vor 5 Jahren 0
0
A. Donda

Kamil Maciorowskis Antwort ist sehr gut, aber ich denke, dass seine Lösung in dem in der Frage beschriebenen Kontext mit dem folgenden Verfahren rationalisiert werden kann:

1) Erstellen Sie eine Prüfsummendatei in der Quelle. Hier ist ein Bash-Skript, das dies mit Hilfe von cfv:

#!/bin/bash  # create md5 checksum file for all files in the current directory tree  # filename for checksum file FN="$.md5"  # create checksum file cfv -rr -C -L -t md5 -f $FN 

Es beginnt mit dem aktuellen Verzeichnis, geht rekursiv nicht symbolischen Links nach und erstellt eine einzige Prüfsummendatei im aktuellen Verzeichnis.

2) Synchronisieren / Kopieren von Quelle zu Ziel.

3) Überprüfen Sie die Prüfsumme Datei auf dem Ziel (mit cfv), und suchen Sie nach weiteren Dateien mit find, sortund comm:

#!/bin/bash  # test md5 checksum file w.r.t. all files in the current directory tree  # filename for checksum file FN="$.md5"  # test checksum file cfv -T -f $FN  # check whether there are additional files echo ----------- additional files ----------- CHECK=`tempfile` sed 's .\ ' $FN | sort > $CHECK LOCAL=`tempfile` find -P -type f -printf '%P\n' | sort > $LOCAL comm -13 $CHECK $LOCAL 

Der Unterschied zu Kamil Maciorowskis Antwort ist, dass ich keine separate Dateiliste für die Quelle erstelle, sondern die Dateinamen in der Prüfsummen-Datei verwende, die über extrahiert werden sed. Dies setzt voraus, dass die Prüfsummendatei im Standardformat md5sumvorliegt: 32 Zeichen Prüfsumme, Leerzeichen, '*' oder '', um den Binär- / Textmodus, Dateiname anzugeben.