rsync Verzeichnisse vergleichen?

63

Ist es möglich, zwei Verzeichnisse mit rsync zu vergleichen und nur die Unterschiede auszudrucken? Es gibt eine Trockenlaufoption, aber wenn ich die Ausführlichkeit auf ein bestimmtes Maß erhöhe, wird jede verglichene Datei angezeigt.

ls -alRund diffist hier keine Option, da es Hardlinks in der Quelle gibt, die jede Zeile anders machen. (Natürlich könnte ich diese Spalte mit Perl löschen.)

chris
quelle
Ähnlich: serverfault.com/questions/62364/…
reinierpost 29.10.15

Antworten:

46

Sie müssen wahrscheinlich rsync -avun --deletein beide Richtungen laufen .

Aber was versuchst du eigentlich zu erreichen?

Update :

rsync -avun --delete $TARGET $SOURCE |grep "^deleting " Sie erhalten eine Liste der Dateien, die im Zielverzeichnis nicht vorhanden sind.

"grep delet", da jede Zeile Folgendes ausgibt : delet ing ..file ..

rsync -avun $SOURCE $TARGET Sie erhalten eine Liste mit "verschiedenen" Dateien (einschließlich neuer Dateien).

Nils
quelle
49

Um die Antwort von Nils zu ergänzen (für alle, die über Google darauf stoßen), werden standardmäßig rsyncnur die Dateigrößen und Änderungszeiten verglichen , um festzustellen , ob es Unterschiede gibt. (Wenn diese unterschiedlich sind, bewirkt dies mehr, aber wenn sie gleich sind, hört es dort auf.)

Wenn Sie aktuelle Datei vergleichen wollen Inhalte , auch für Dateien , die die gleiche Größe und Zeitpunkt der letzten Änderung haben, fügen Sie die Flagge -czu sagen , rsyncdie Dateien mit einer Prüfsumme zu vergleichen.

rsync -avnc $SOURCE $TARGET

(Die -uOption weist rsync an, Dateien zu ignorieren, die neuer sind $TARGETals on $SOURCE, was Sie wahrscheinlich nicht möchten, wenn Sie Inhalte vergleichen.)

user98393
quelle
6
Wenn es Ihnen nur wichtig ist, dass die Daten identisch sind, möchten Sie --no-group --no-owner --no-perms --no-timesdiese je nach Ihren Anforderungen möglicherweise hinzufügen oder kombinieren.
flungo
1
@flungo, oder verwenden Sie einfach eine Teilmenge der Optionen, die impliziert werden, -aanstatt -azBrsync -rlDcnv --delete $SOURCE $TARGET
maxschlepzig
Bitte --deletezur Liste hinzufügen nur existierende Dateien in$TARGET
Tom Hale
25

Nur für diejenigen, die weniger vertraut sind mit rsync:

rsync -rvnc --delete ${SOURCE}/ ${DEST}
  • -n: Wichtigstes Bit - nichts ändern;
  • -rc: nur den Inhalt vergleichen (sonst verwenden -ac);
  • -v : Liste der Dateien)
  • --delete : Suchen Sie nach einem symmetrischen, nicht nach einem unidirektionalen Unterschied.
  • Schließlich /bedeutet "In das Verzeichnis schauen und dessen Inhalt mit dem Ziel vergleichen".

Es wird eine übliche rsyncAusgabe gedruckt ,

  • mit einem <Dateinamen> in einer Zeile für jede "neue" Datei in${SOURCE}
  • und eine Zeile "<Dateiname> löschen" für jede "neue" Datei in ${DEST}.

  • Möglicherweise werden auch einige Warnungen ausgegeben, z. B. "Nicht reguläre Datei <Dateiname> wird übersprungen" für Symlinks.

PS. Ich weiß, es ist eine schreckliche PS - aber es wurde in der Tat in Eile hinzugefügt. Trotzdem, ich wette, man kann dies nützlich finden.


PPS. Alternativ könnte man auch tun

find $SOURCE -type f -exec md5sum {} \; | tee source.md5
find $DEST   -type f -exec md5sum {} \; | tee dest.md5

Wenn die Dateinamen keine Zeilenumbrüche enthalten, können wir beide *.md5Dateien und diffdiese sortieren . (Dies funktioniert jedoch nur für Dateien. Das heißt, ein leeres Verzeichnis auf beiden Seiten wird nicht erkannt.)

ジ ジ ー ー
quelle
15

Überraschenderweise nutzt keine Antwort in 6 Jahren die -iOption oder gibt eine gute Ausgabe aus.

TLDR - Zeigen Sie mir einfach die Befehle

rsync -rin --ignore-existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^[^ ]* /L             /'
rsync -rin --ignore-existing "$RIGHT_DIR"/ "$LEFT_DIR"/|sed -e 's/^[^ ]* /R             /'
rsync -rin --existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^/X /'

Die Ausgabe verstehen

Hier ist ein Beispiel für die Ausgabe:

L             file-only-in-Left-dir
R             file-only-in-right-dir
X >f.st...... file-with-dif-size-and-time
X .f...p..... file-with-dif-perms

Beachten Sie das erste Zeichen jeder Zeile:

  • L/ Rbedeutet, dass die Datei / dir nur in der LEFT- oder REIGHT-Richtung angezeigt wird.
  • Xbedeutet , dass die Datei auf beiden Seiten erscheint , ist aber nicht das gleiche (in diesem Fall die nächsten 11 Zeichen geben Ihnen weitere Informationen. s, tund pzeigen Unterschiede in s ize, t ime und p ermissions jeweils - für weitere Informationen versuchen man rsyncund suchen --itemize-changes) .

Zusätzliche Optionen, die Sie möglicherweise verwenden möchten

Wenn Sie auch den Eigentümer / die Gruppe / die Berechtigungen der Dateien vergleichen möchten, fügen Sie die Optionen -o/ -g/ hinzu -p. Beachten Sie schließlich, dass rsync standardmäßig zwei Dateien als gleich ansieht, wenn sie denselben Namen, dieselbe Zeit und dieselbe Größe haben. Dies ist extrem schnell und in den meisten Fällen mehr als ausreichend. Wenn Sie jedoch 100% sicher sein möchten, -cvergleichen Sie auch den Inhalt von Dateien mit demselben Namen, derselben Zeit und Größe.

TLDR - Gib mir einfach ein Skript zum Anrufen

Hier ist es. Nenne es so

diff-dirs Left_Dir Right_Dir [options]

Alle oben im Abschnitt "Zusätzliche Optionen, die Sie möglicherweise verwenden möchten" genannten Optionen gelten auch hier.

#!/bin/bash
# Compare two directories using rsync and print the differences
# CAUTION: options MUST appear after the directories
#
# SYNTAX
#---------
# diff-dirs Left_Dir Right_Dir [options]
#
# EXAMPLE OF OUTPUT
#------------------
# L             file-only-in-Left-dir
# R             file-only-in-right-dir
# X >f.st...... file-with-dif-size-and-time
# X .f...p..... file-with-dif-perms
#
# L / R mean that the file/dir appears only at the `L`eft or `R`ight dir. 
#
# X     means that a file appears on both sides but is not the same (in which
#       case the next 11 characters give you more info. In most cases knowing
#       that s,t,T and p depict differences in Size, Time and Permissions 
#       is enough but `man rsync` has more info
#       (look at the --itemize-changes option)
#
# OPTIONS
#---------
# All options are passed to rsync. Here are the most useful for the purpose
# of directory comparisons:
#
# -c will force comparison of file contents (otherwise only
#    time & size is compared which is much faster)
#
# -p/-o/-g will force comparison of permissions/owner/group

if [[ -z $2 ]] ; then
    echo "USAGE: $0 dir1 dir2 [optional rsync arguments]"
    exit 1
fi

set -e

LEFT_DIR=$1; shift
RIGHT_DIR=$1; shift
OPTIONS="$*"

# Files that don't exist in Right_Dir
rsync $OPTIONS -rin --ignore-existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^[^ ]* /L             /'
# Files that don't exist in Left_Dir
rsync $OPTIONS -rin --ignore-existing "$RIGHT_DIR"/ "$LEFT_DIR"/|sed -e 's/^[^ ]* /R             /'
# Files that exist in both dirs but have differences
rsync $OPTIONS -rin --existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^/X /'

Wie funktioniert es?

Wir rufen Rsync folgendermaßen auf:

rsync -rin ...

Wir verwenden -i( --itemize-changes), um rsync anzuweisen, eine Ausgabezeile für jede Datei zu drucken, die Informationen über Unterschiede zwischen den beiden Verzeichnissen enthält. Wir müssen -ndas normale Verhalten von rsync unterdrücken (dh versuchen, die beiden Verzeichnisse durch Kopieren / Löschen von Dateien zu synchronisieren). Wir müssen auch -rrekursiv für alle Dateien / Unterverzeichnisse arbeiten.

Wir rufen rsync dreimal auf:

1. Aufruf : Druckt Dateien, die in Dir_B nicht existieren. Wir müssen verwenden --ignore-existing, um Dateien zu ignorieren, die auf beiden Seiten existieren.

rsync -rin --ignore-existing $DIR_A/ $DIR_B/

2. Aufruf : Genau wie zuvor, aber wir tauschen die Reihenfolge von DIR_A / DIR_B.

3. Aufruf : Schließlich --existingprüfen wir nur die Dateien, die in beiden Verzeichnissen erscheinen.

rsync -rin --existing $DIR_A/ $DIR_B/
ndemou
quelle
Ich weiß nichts über andere, aber ich verwende Ihr Skript. Gute Arbeit! danke
Marinaio
7

Ich verstehe aus Ihrer Frage, dass Sie diff nicht für ls verwenden möchten , aber Sie können diff auch rekursiv für Verzeichnisse verwenden:

diff -rq DIR1 DIR2
Camion
quelle
2

Ich brauchte ein paar Versuche, um das zum Laufen zu bringen. Nils 'Antwort erfordert, dass sie $TARGETmit einem Trailing endet /, wie es durch ジ ジ ー explained erklärt wird.

Hier ist eine Version, die das Trailing explizit hinzufügt /:

rsync -avun --delete ${TARGET}/ ${SOURCE}  | sed -ne 's/^deleting *//p'

Dies gibt die Liste der Dateien an, die unterhalb des ${SOURCE}Verzeichnisses existieren, jedoch nicht unterhalb des ${TARGET}Verzeichnisses.

Ich benutze sedhier, um die führenden deletingZeilen aus den Ausgabezeilen zu entfernen und nur diese Zeilen zu drucken.

Ich verwende diese rsyncOption nicht, -cda der Vergleich von Dateiinhalten in meinen Anwendungsfällen sehr viel langsamer wäre und auch in diesen Fällen der Vergleich nur von Dateigrößen und Änderungszeiten ausreichend erscheint. Ich habe keinen Grund zu der Annahme, dass meine Computer Probleme mit dem Zeitversatz haben oder dass sich die Zeitstempel auf böswillige Weise geändert haben. Das Ergebnis von -ckann nicht die Entscheidung zum Löschen einer Datei ändern, sondern nur die Entscheidung zum Aktualisieren oder Aufbewahren einer Datei.

Ich benutze auch -uund -a(nicht -r), so dass ich später den Zeilenbefehl wieder verwenden und verändern ausgewählte Verzeichnisse und Dateien aus kopieren ${SOURCE}zu ${TARGET}, wie folgt aus :

rsync -avu ${SOURCE}/{dirA,dirB,fileX} ${TARGET}   # copy some files
Orafu
quelle
0

Ich habe eine andere Idee, dies zu tun:

rsync -rn --out-format=FILEDETAIL::%n  $TARGET $SOURCE  | grep "^FILEDETAIL"

Sie können "FILEDETAIL ::" mit der Ausgabe des Befehls abgleichen. Sie können auch die Zeichenfolge "FILEDETAIL ::" ändern. Das "% n" ist der Dateiname.

-r Weist rsync an, Verzeichnisse rekursiv zu kopieren.

-n Damit führt rsync einen Testlauf durch, bei dem keine Änderungen vorgenommen werden.

Zhao Tony
quelle