Was ist die beste Möglichkeit, unter Linux zwei Verzeichnisse im selben Dateisystem zusammenzuführen?

Was ist die beste Möglichkeit, unter Linux zwei Verzeichnisse im selben Dateisystem zusammenzuführen?

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, mvkopieren 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 rsyncmit --remove-source-filesOption. 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 mvdies fehlschlägt. Hier sind einige Beispieldaten:

mkdir -p src/d dest/d
touch src/d/f1 dest/d/f2

Sehen Sie, wie es mvfehlschlä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 echobefore 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 srcaufräumen.

Antwort3

mvBei 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.

verwandte Informationen