
Ich habe zwei Verzeichnisse, die zusammengeführt werden müssen. Die Dateien in diesen beiden Verzeichnissen sind alle groß (>= 500 MB).
Was ich archivieren möchte: Für Dateien im Quellverzeichnis: Wenn sie im Zielverzeichnis nicht vorhanden sind, mv
kopieren Sie sie in das Zielverzeichnis (was schnell geht, da wir grundsätzlich einen neuen Hardlink erstellen und die Verknüpfung der Quelldatei aufheben); wenn sie im Zielverzeichnis vorhanden sind, kopieren Sie die Quelldatei dorthin und entfernen Sie die Quelldatei.
Die gängigste Methode zum Zusammenführen von Verzeichnissen im Linux-System ist die Verwendung rsync
mit --remove-source-files
Option. Dies ist jedoch langsam, da der Kopiervorgang auch dann ausgeführt wird, wenn die Zieldatei nicht vorhanden ist.
Irgendwelche besseren Ideen? Danke.
Antwort1
Im Grunde haben Sie beschrieben, dass Sie Dateien verschieben und das Ziel überschreiben, falls vorhanden. Verschieben Sie sie also einfach.
Antwort2
Es gibt einen Fall, in dem mv
dies fehlschlägt. Hier sind einige Beispieldaten:
mkdir -p src/d dest/d
touch src/d/f1 dest/d/f2
Sehen Sie, wie es mv
fehlschlägt:
$ mv src/* dest/
mv: cannot move 'src/d' to 'dest/d': Directory not empty
$ mv -f src/* dest/
mv: cannot move 'src/d' to 'dest/d': Directory not empty
$ mv -fv src/* dest/
mv: cannot move 'src/d' to 'dest/d': Directory not empty
$ mv -fvi src/* dest/
mv: overwrite 'dest/d'? y
mv: cannot move 'src/d' to 'dest/d': Directory not empty
$ mv -fvi -t dest/ src/*
mv: overwrite 'dest/d'? y
mv: cannot move 'src/d' to 'dest/d': Directory not empty
Erstellen Sie also eine Skriptdatei:
vim supermove
Dieses Beispiel führt keine Fehlerprüfung durch (HAFTUNGSAUSSCHLUSS: funktioniert bei mir, aber testen Sie bitte, ob es bei Ihnen funktioniert ... vielleicht mit echo
before mv
) und überschreibt Dateien mit demselben Pfad. Und es verwendet find mit, \;
was furchtbar ineffizient ist, aber +
mit vorangestelltem nicht richtig funktioniert "$dest"
. Ältere Versionen erstellen einige Verzeichnisse ohne vorangestellten Pfad und neuere Versionen von find sagen:
find: In '-exec ... {} +' the '{}' must appear by itself, but you specified 'dest/{}'
Sie könnten das aber wahrscheinlich mit xargs beheben. (Bei den 64.000 Dateien (8 TB), die ich verschoben habe, hat es ein paar Minuten gedauert.) Fügen Sie diesen Inhalt hinzu:
#!/bin/bash
src=$1
dest=$2
src=$(readlink -f "$src")
dest=$(readlink -f "$dest")
cd "$src"
# also copy hidden files
shopt -s dotglob
# make dirs (missing old permission,acl,xattr data), and then mv the files
time find * -type d -exec mkdir -p "$dest"/{} \;
time find * -type f -exec mv {} "$dest"/{} \;
# also copy permissions, acls, xattrs
rsync -aAX "$src"/ "$dest"/
Und machen Sie es ausführbar:
chmod +rx supermove
Und führen Sie es aus
./supermove src/ dest/
Und das Ergebnis... vorher:
$ find src dest
src/
src/d
src/d/f1
dest/
dest/d
dest/d/f2
Nach:
$ find src dest
src
src/d
dest
dest/d
dest/d/f1
dest/d/f2
Jetzt src/
sollten nur noch leere Verzeichnisse vorhanden sein. Wenn ja, können Sie rm -r src
aufräumen.
Antwort3
mv
Bei den Optionen dreht es sich alles um Konfliktlösung:
Wähle eins:
-f force (always overwrite)
-i interactive (ask whether to overwrite)
-n no clobber (no overwrite)
Und das ist auch gut:
-v verbose
Andernfalls können Daten verloren gehen und/oder es ist nicht klar, was genau passiert ist.
mv ist auf demselben FS auch überlegen, da es nur Verzeichnis-Inodes aktualisiert und die Dateien nicht manipuliert werden sollten. Außerdem besteht bei größeren Vorgängen eine größere Wahrscheinlichkeit, dass etwas schief geht, z. B. Soft-Fehler.