Vergleiche 2 Verzeichnisse und kopiere Unterschiede in ein 3. Verzeichnis

32

Unter Ubuntu 12.04 möchte ich 2 Verzeichnisse vergleichen, z. B. Ordner1 / und Ordner2 /, und alle Dateien kopieren, die sich von Ordner3 / unterscheiden. Es gibt auch verschachtelte Dateien, daher sollten auch passende Unterverzeichnisse kopiert werden

Gibt es einen einzigen Befehl, der mir helfen würde? Ich kann die vollständige Liste der geänderten Dateien abrufen:

rsync -rcnC --out-format="%f" folder1/ folder2/

Rsync scheint jedoch nicht in der Lage zu sein, diese Dateien in ein anderes Zielverzeichnis zu "exportieren". Kann ich die Liste an cp oder ein anderes Programm leiten, damit die Dateien kopiert werden, während auch die Verzeichnisse erstellt werden? Ich habe es zum Beispiel versucht

rsync -rcnC --out-format="%f" folder1/ folder2/ | xargs cp -t folder3/

aber das würde auch keine Verzeichnisse erhalten, es würde einfach alle Dateien innerhalb von folder3 / kopieren

Periklis
quelle
Ich würde wahrscheinlich eine Kombination von diff -qrund verwenden awk, um die Liste zu erstellen, dann rsync...
ewwhite
Wie würde ich rsync mit der Liste verwenden?
Periklis
Ich würde entweder eine for-Schleife ausführen oder die rsync --include-from=FILEOption verwenden.
ewwhite
(nicht faul sein ...) Aber die unten stehende Rsync-Lösung ist elegant.
Ewwhite

Antworten:

37

Verwenden Sie --compare-dest.

Von der Manpage:

--compare-dest = DIR - Diese Option weist rsync an, DIR auf dem Zielcomputer als zusätzliche Hierarchie zu verwenden, um Zieldateien mit Übertragungen zu vergleichen (wenn die Dateien im Zielverzeichnis fehlen). Wenn in DIR eine Datei gefunden wird, die mit der Datei des Absenders identisch ist, wird die Datei NICHT in das Zielverzeichnis übertragen. Dies ist nützlich, um nur eine Sicherungskopie von Dateien zu erstellen, die gegenüber einer früheren Sicherung geändert wurden.

Überprüfen Sie zuerst Ihre Syntax mit --dry-run

rsync -aHxv --progress --dry-run --compare-dest=folder2/ folder1/ folder3/

Dann, wenn Sie mit der Ausgabe zufrieden sind:

rsync -aHxv --progress  --compare-dest=folder2/ folder1/ folder3/

Dieser Link enthält eine gute Erklärung des --compare-dest-Bereichs.

Schmiede
quelle
1
Vielen Dank dafür, dass ich die Manpage-Erklärung dieses Parameters nicht verstanden habe. Für alle Interessierten habe ich es mitrsync -rcC --compare-dest=folder2/ folder1/ folder3/
periklis
Kurznotiz für OsX-Benutzer. Ich habe rsync version 3.1.1 protocol version 31auf meinem lokalen und Rsync versteht keine ~/Pfade für --compare-destparam.
Jevgeni Smirnov
3
Für mich war --compare-destein absoluter Weg gefragt.
Palswim
Funktionierte weder mit den Optionen des Autors noch mit den Optionen des OP. Dh es wird eine fonts/Makefile.inDatei ausgegeben , die sowohl in folder2als auch in folder1dirs identisch ist .
Hi-Angel
3

Dieses kleine Skript sollte funktionieren:

folder1="firsts_folder/"
folder2="second_folder/"
folder3="target_folder"
for x in `rsync -rcnC --out-format="%n"  $folder1 $folder2`
    do
        if [ -d "$folder1/$x" ]; then
            mkdir -p "$folder3/$x"
        else
            cp -frv $folder1/$x $folder3/$x
        fi
done

Aber ich denke auch, dass das Parsen der Ausgabe von diff -qr eine bessere Lösung wäre, da es Ihnen Pfad und Namen für jede Datei konsistent gibt.

BEARBEITEN

Dies wäre ein Befehl, Ihr Befehl leicht modifiziert. Aber es wird folder1unter dem schaffen folder3. Und es funktioniert nicht mit vollständigen Pfaden, aber auch das obige Skript funktioniert nicht mit vollständigen Pfaden.

rsync -rcnC --out-format="\"%f\"" folder1/ folder2/ | xargs cp --parents -rfvt folder3/

Ich habe \"in verwendet rsync, damit es mit Dateien und Verzeichnissen funktioniert, die Leerzeichen enthalten. Getestet unter Ubuntu 10.04. Ich hoffe es hilft.

Laurentiu Roescu
quelle
danke dafür hatte ich gehofft, dass es einen einzigen befehl geben würde
periklis
2
rsync -rcnC --out-format="%f" . ../folder2/ |xargs cp --parents -rt ../folder3/

Das ist die einfachste Form, die ich mir einfallen lassen könnte, wenn Sie bereit sind, sich folder1vor dem Ausgeben des Befehls zuerst zu begeben.

Dies ist die langsamere Option, aber ich glaube, sie entspricht Ihren Anforderungen und kann mit nicht relativen Verzeichnisnamen ausgeführt werden:

rsync -rcnC --out-format="%n" folder1/ folder2/ |grep -vP "/$" |xargs -I{} rsync -R folder1/./{} folder3/

Ich habe Ihren ursprünglichen rsyncBefehl in Ruhe gelassen, weil Sie sagten, er gebe Ihnen die richtige Dateiliste (und meine Testdateien unterscheiden sich offensichtlich von Ihren, sodass ich nicht mit Sicherheit sagen konnte, dass ich die richtige Dateiliste erhalten würde, wenn ich Fehler mache damit).

Das grepist es Verzeichnisnamen aus dem Ausgang der zu entfernen rsync.

Die Ausgabe von grepwird dann an eine andere rsyncVerwendung weitergeleitet xargs. Im Parameter wird folder1/./{}das Extra ./verwendet, um rsync anzuweisen , die relativen Verzeichnisse beginnend mit zu erstellen ./{}und zu ignorieren folder1/. Mit anderen Worten, es vermeidet das Erstellen folder3/folder1/.

Ich konnte dies nur auf CentOS 6.4 testen, aber AFAIK sollte es in Ubuntu 12.04 genauso funktionieren.

EDIT: Ich sollte zur Kenntnis nehmen, dass die Antwort von Smithian zweifellos besser ist, aber ich wollte versuchen, es mit Ihrem ursprünglichen rsyncBefehl im Takt zu tun, da es Ihnen die gewünschte Ausgabe gab.

s.co.tt
quelle