Best Practice, um fortzufahren mv

13

Ich habe das Terminal verwendet, um Dateien von einem Laufwerk auf ein anderes zu kopieren.

sudo mv -vi /location/to/drive1/ /location/to/drive2/

Dies hörte jedoch nach einigen Stunden ohne Fehler nach dem Erstellen eines Verzeichnisses plötzlich auf.

Meine eigene Lösung dafür ist oft eine Mischung aus Hashing und Vergleichen, was meistens ein zeitaufwändiges Chaos ist, da ich jetzt eine Zwischenkopie wiederherstellen muss, ohne wirklich zu wissen, welche Dateien fehlen (geschrieben als sehr langer Einzeiler für zsh - beachte das Dieses Skript funktioniert nicht in Bash (wie geschrieben):

source_directory="/path/to/source_directory/";
target_directory="/path/to/target_directory/";
while read hash_and_file; do {
    echo "${hash_and_file}" | read hash file;
    echo "${file}" | sed "s/^/${source_directory}/g" | read copy_from;
    echo "${copy_from}" | sed "s/${source_directory}/${target_directory}/g" | read copy_to;
    mv -v "${copy_from}" "${copy_to}" | tee -a log;
    rm -v "${copy_from}" | tee -a log; };
done <<<$(
    comm -23 <( find ${source_directory} -type f -exec sha256sum "{}" \; |
                sed "s: ${source_directory}: :g" | sort;
           ) <( find ${target_directory} -type f -exec sha256sum "{}" \; |
                sed "s: ${target_directory}: :g" | sort; ) )

Dies ist fehleranfällig, wenn der Name Zielverzeichnis oder Quellverzeichnis Teil des Pfads ist. Löschen Sie Dateien, wenn sie nicht verschoben wurden, weil sie als Duplikate markiert waren. Außerdem wird am Ende kein Quellverzeichnis erstellt.

Gibt es eine bewährte Methode zum Wiederherstellen von unterbrochenen MV?

Was
quelle
Ich habe ein ähnliches Skript geschrieben , das cmpanstelle von Hashing verwendet wird. Es hat Abhängigkeiten und die gleichen Probleme while readwie Gilles. Es ist auch langsam und wortreich. Es wird jedoch schneller als mit der rsync-Methode Speicherplatz freigegeben, da Dateien während der Ausführung (erneut) aus dem Quellcode verschoben werden. Es kann als Inspiration für die Mutigen dienen.
Joeytwiddle
3
rsync Angebote @joeytwiddle --delete-during receiver deletes during the transferund auch mehrere andere nützliche Alternativen: --delete --delete-before --delete-delay --delete-after --delete-excluded. Also, ja, rsync ist die beste Alternative
Isaac
Ich muss etwas vermissen. Warum funktioniert es nicht einfach, den gleichen mvBefehl zu wiederholen ? Möglicherweise mit *angefügtem Quellpfad, wenn die ursprüngliche Quelle ein Verzeichnis war.
jpa
@isaac Nein, ich fürchte, das rsync --delete*wäre eine Katastrophe ! Es wird entfernen Dinge von destdenen sind derzeit nicht in src, so dass alle Dateien , die erfolgreich im vorherigen Versuch verschoben wurden , werden nun gelöscht! Sie haben wahrscheinlich darüber nachgedacht, rsync --remove-source-fileswas meiner Meinung nach eine gute Alternative wäre. ( more1 , more2 )
joeytwiddle
@joeytwiddle Nein, rsync --deletewird nur entfernen andere Dateien , die nicht Teil der Quelle sind. Von [man rsync] () * Löschen Sie nicht benötigte Dateien aus den Zielverzeichnissen *. Verstehen Sie, was Fremdes bedeutet: Nicht synchronisiert werden. Und ja, rsync bietet auch die Möglichkeit, Quelldateien nach der korrekten Übertragung zu entfernen.
Isaac

Antworten:

46

Vergessen Sie den Versuch, rsync neu zu erfinden, und verwenden Sie rsync.

sudo rsync -av /location/to/drive1/ /location/to/drive2/

Stellen Sie sicher, dass Sie einen abschließenden Schrägstrich in der Quelle verwenden, da er andernfalls nach kopiert werden würde /location/to/drive2/drive1.

Stellen Sie sicher, dass der Befehl erfolgreich ausgeführt wurde, und führen Sie ihn dann aus rm -rf /location/to/drive1/.

Der obige Befehl überschreibt alle bereits vorhandenen Dateien von drive2. Wenn Sie den Benutzer auffordern möchten, bereits vorhandene Dateien zu überspringen drive2, ist dies wie bei mv -ikomplizierter, da Sie jetzt zwischen bereits kopierten und nicht kopierten Dateien unterscheiden müssen. Sie können die --ignore-existingOption an rsync übergeben, um Dateien zu überspringen, die bereits auf dem Ziel vorhanden sind, unabhängig von ihrem Inhalt. Beachten Sie, dass, wenn das Original mvwährend der Erstellung einer Datei unterbrochen wurde, diese Datei in ihrem halb kopierten Zustand verbleibt (wohingegen eine leere Datei das rsync -aKopieren ordnungsgemäß beenden würde).

Wenn Sie das genaue Verhalten mv -i, einschließlich der Eingabeaufforderung, reproduzieren möchten , können Sie dies tun, aber es ist viel komplizierter.

Beachten Sie, dass Ihr Ein-Riesen-Liner sehr zerbrechlich ist. Wenn es Dateinamen gibt, die Backslashes oder Newlines enthalten, werden sie möglicherweise nicht richtig kopiert oder sie können sogar Ihr Skript dazu verleiten, beliebige Dateien zu entfernen. Also den Code nicht in der Frage verwenden , wenn Sie sicher sind , dass Sie die Dateinamen vertrauen können nicht Schrägstriche oder Zeilenumbrüche enthalten.

Zum späteren Nachschlagen empfehle ich, niemals mvfür große Cross-Drive-Bewegungen zu verwenden, gerade weil es schwierig ist zu kontrollieren, was passiert, wenn es unterbrochen wird. Kopieren Sie mit rsync und entfernen Sie das Original.

Gilles 'SO - hör auf böse zu sein'
quelle
Was verspricht rsync, was mv nicht verspricht?
Was
4
Nun, zum Beispiel rsyncmacht das, was du versuchst, mvaber nicht. Auch: Kopieren zwischen verschiedenen Maschinen; Komprimierung für die Übertragung; Überspringen von Dateien, die am Zielort vorhanden sind, basierend auf zeitstempel- oder hashbasierter Gleichheit; konfigurierbarer Umgang mit Inhabern, Berechtigungen, Links und speziellen Dateien; etc. linux.die.net/man/1/rsync
Silly Freak
1
@SillyFreak sollte ich daraus schließen, dass ich immer rsync anstelle von mv verwenden sollte, nicht nur wie Gilles für Cross-Drive sagte, sondern jede Operation, da die Grenze von "zu groß" relativ subjektiv ist und es zu einem Problem kommt wäre es trotzdem durch rsync gelöst worden?
Was
9
Wenn ich Dateien oder Verzeichnisse innerhalb einer Partition verschiebe, verwende ich normalerweise mv(oder den Dateimanager), weil es nur einen Verweis auf die Datei / das Verzeichnis verschiebt. Wenn ich die eigentliche Datenübertragung durchführen muss, verwende ich, rsyncwenn eine der folgenden Bedingungen erfüllt ist: 1) Ich verschiebe mehr Dateien, als ich auf einen Blick auf die korrekte Übertragung überprüfen kann. 2) Ich gehe davon aus, dass ich die Dateien synchron halten muss. 3) Ich gehe davon aus, dass die Übertragung unterbrochen werden könnte. Mein Punkt ist, für den Anwendungsfall, den Sie in der Frage präsentieren, rsyncist einfach das richtige Werkzeug, und mvoder cpnicht.
Dumme Freak
7
Ich würde empfehlen, jeden rsync-Befehl immer mit -v und -dry-run auszuführen, um genau zu bestätigen, was er tun wird.
Darren