Ich möchte eine Reihe von Dateien von Verzeichnis A in Verzeichnis B kopieren, mit dem Vorbehalt, dass, wenn eine Datei in Verzeichnis A mit einer Datei in Verzeichnis B identisch ist, diese Datei nicht kopiert werden sollte (und daher ihre Änderungszeit nicht sein sollte) aktualisiert). Gibt es eine Möglichkeit, dies mit vorhandenen Tools zu tun, ohne dafür ein eigenes Skript zu schreiben?
Um ein wenig auf meinen Anwendungsfall einzugehen: Ich .c
erstelle automatisch eine Reihe von Dateien in einem temporären Verzeichnis (mit einer Methode, die alle Dateien bedingungslos generieren muss), und wenn ich sie erneut generiere, möchte ich nur kopieren Diejenigen, die sich in das eigentliche Quellverzeichnis geändert haben, lassen die unveränderten (mit ihren alten Erstellungszeiten) unberührt, make
damit Sie wissen, dass sie nicht neu kompiliert werden müssen. (Da es sich bei nicht allen generierten Dateien um .c
Dateien handelt, muss ich eher binäre Vergleiche als Textvergleiche durchführen.)
(Als Hinweis: Dies ergab sich aus der Frage, die ich unter https://stackoverflow.com/questions/8981552/speeding-up-file-comparions-with-cmp-on-cygwin/8981762#8981762 gestellt hatte , wo ich es versuchte Um die Skriptdatei zu beschleunigen, die ich für diese Operation verwendet habe, sollte ich mich wirklich fragen, ob es einen besseren Weg gibt, als mein eigenes Skript zu schreiben - zumal es eine einfache Möglichkeit gibt, dies in einer Shell zu tun Das Skript ruft so etwas wie cmp
für jedes Dateipaar auf, und das Starten all dieser Prozesse dauert zu lange.)
quelle
diff -qr dirA dirB
um zu sehen , welche Dateien sind einzigartigdirA
unddirB
, repectively.rsync -avnc
oder den langen Wegrsync --archive --verbose --dry-run --checksum
.Antworten:
rsync ist wahrscheinlich das beste Tool dafür. Es gibt viele Optionen für diesen Befehl, lesen Sie die Manpage . Ich denke, Sie wollen die Option --checksum oder --ignore-times
quelle
-t
Option angegeben ist) oder auf die Synchronisationszeit aktualisiert (falls-t
nicht angegeben).rsync
nicht. Wenn ich dies tuemkdir src dest; echo a>src/a; rsync -c src/* dest; sleep 5; touch src/a; rsync -c src/* dest
, dannstat dest/a
zeigt es, dass mtime und ctime 5 Sekunden älter sind als diejenigen vonsrc/a
.--checksum
Option zu sein, und obwohl linux.die.net/man/1/rsync absolut nichts enthält , was darauf schließen lässt, dass es einen Einfluss darauf hat, ob das Änderungsdatum aktualisiert wird, bewirkt es dennoch, dass das Änderungsdatum des Ziels übrig bleibt unberührt. (Auf der anderen Seite hat die--ignore-times
Option diesen Effekt nicht. Damit wird das Änderungsdatum immer noch aktualisiert.) Kann ich mich jedoch darauf verlassen, da dies völlig undokumentiert zu sein scheint?rsync
's Workflow ist: 1) Überprüfen Sie, ob die Datei aktualisiert werden muss; 2) Aktualisieren Sie in diesem Fall die Datei. Die--checksum
Option sollte nicht aktualisiert werden und daherrsync
nicht mit Schritt 2 fortfahren.--ignore-times
Ohne--checksum
würde jede Datei kopiert und so auch der Zeitstempel aktualisiert, auch wenn die Dateien identisch sind.Sie können den
-u
Schalter verwenden, um Folgendes zucp
mögen:Von der Manpage:
quelle
-u
Flag macht und wie es funktioniert und wie dies dem OP helfen würde. In diesem speziellen Fall würde es dem OP jedoch nicht helfen, da identische Dateien kopiert würden, wenn sie neuer wären, und so ihre Zeitstempel geändert würden, was genau das ist, was das OP vermeiden möchte.Während die Verwendung
rsync --checksum
eine gute allgemeine Möglichkeit zum "Kopieren bei Änderung" ist, gibt es in Ihrem speziellen Fall eine noch bessere Lösung!Wenn Sie vermeiden möchten, dass Dateien unnötig neu kompiliert werden, sollten Sie den Ccache verwenden, der genau für diesen Zweck erstellt wurde! Tatsächlich werden dadurch nicht nur unnötige Neukompilierungen Ihrer automatisch generierten Dateien vermieden, sondern es werden auch die Dinge beschleunigt, wann immer Sie dies tun
make clean
und von Grund auf neu kompilieren.Als nächstes werden Sie sicher fragen: "Ist es sicher?" Nun, ja, wie die Website feststellt:
Und es ist einfach zu verwenden , indem Sie es einfach als Präfix in die
CC=
Zeile Ihres Makefiles einfügen (oder Sie können Symlinks verwenden, aber der Makefile-Weg ist wahrscheinlich besser).quelle
ccache file.c -o file.o
mehrere hundert Mal aufrufen , weil es mehrere hundertfile.c
Dateien gibt. Wenn ich tat , dass mitcmp
, anstattccache
, dauerte es mehrere Minuten - undcmp
ist so leicht wieccache
. Das Problem ist, dass das Starten eines Prozesses unter Cygwin nicht unerhebliche Zeit in Anspruch nimmt, selbst für einen völlig trivialen Prozess.for f in src/*; do /bin/true.exe; done
30 Sekunden. Auf jeden Fall bevorzuge ich meinen Windows-basierten Editor und abgesehen von dieser Art von Zeitproblemen funktioniert Cygwin sehr gut mit meinem Workflow als einfachem Ort, um Dinge lokal zu testen, wenn ich sie nicht auf die Build-Server hochlade. Es ist nützlich, meine Shell und meinen Editor im selben Betriebssystem zu haben. :)Dies sollte tun, was Sie brauchen
Woher:
quelle
-J
ist BSD-spezifisch; mit GNU XARGs ist es das-I
) und nicht richtig funktioniert, wenn nicht an beiden Orten bereits derselbe Satz von Dateien existiert (wenn ichtouch x/boo
dann grep gibt)Only in ./x: boo
was zu Fehlern in der Pipeline führt). Verwenden Sie beispielsweise ein für diesen Job entwickeltes Toolrsync --checksum
.Ich mag verwenden unisono für ,
rsync
weil es mehrere Master unterstützt, nachdem er bereits mein Setup SSH - Schlüssel und vpn getrennt.In meiner Crontab von nur einem Host habe ich sie alle 15 Minuten synchronisieren lassen:
Dann kann ich mich auf beiden Seiten entwickeln und die Veränderungen werden sich verbreiten. Tatsächlich habe ich für wichtige Projekte bis zu 4 Server, die den gleichen Baum spiegeln (3 laufen unisono von cron und zeigen auf denjenigen, der dies nicht tut). Tatsächlich sind Linux- und Cygwin-Hosts gemischt - außer Sie erwarten keinen Sinn von Softlinks in win32 außerhalb der Cygwin-Umgebung.
Wenn Sie diesen Weg gehen, machen Sie den ersten Spiegel auf der leeren Seite ohne die
-batch
, dhNatürlich gibt es eine Konfiguration zum Ignorieren von Backup-Dateien, Archiven usw .:
quelle
unison
Option finden, die bedeutet, dass das Datum der letzten Änderung der Datei nicht aktualisiert wird. Ist dort eines? Ansonsten ist dies eine großartige Antwort auf ein ganz anderes Problem.-times
tut das für mich. Unison hat auch einen Trockenlaufmodus, denkt ich.times=false
(oder aufhören-times
) würde das tun. Ich weiß nicht, wie ich das in der Dokumentation verpasst habe. Vielen Dank!Während
rsync --checksum
ist die richtige Antwort, beachten Sie, dass diese Option mit nicht kompatibel ist--times
, und das--archive
beinhaltet--times
, so dass , wenn Sie möchtenrsync -a --checksum
, die Sie wirklich brauchenrsync -a --no-times --checksum
.quelle