Was passiert, wenn mv unterbrochen wird?

72

Was passiert, wenn der Linux- mvBefehl unterbrochen wird? Angenommen, ich verschiebe ein ganzes Verzeichnis an einen anderen Ort und unterbreche es, während es sich bewegt. Wird das Quellverzeichnis noch unberührt bleiben?

dehmann
quelle

Antworten:

51

Wenn Sie ein Verzeichnis im selben Dateisystem verschieben, verschieben Sie nur den Verzeichniseintrag von einem Speicherort im Dateisystem an einen anderen. ZB mv /source/dir /target/dirlöscht der Verzeichniseintrag von diraus /sourceund erstellt einen neuen in /target. Dies geschieht durch einen atomaren Systemaufruf (dh unterbrechungsfrei). Der Inode, der sowohl die Verzeichniseinträge dirals auch den eigentlichen Inhalt des Verzeichnisses enthält, ist nicht betroffen.

Wenn Sie das Verzeichnis von einem Dateisystem in ein anderes verschieben, werden alle Dateien zuerst in das neue Dateisystem kopiert und anschließend von dem ursprünglichen Dateisystem getrennt. Wenn Sie mvden Kopiervorgang unterbrechen , erhalten Sie möglicherweise zwei Kopien einiger Dateien - am alten und am neuen Speicherort.

bmk
quelle
6
@Wesley: Nein, es wird keine Teildatei geben. Bleibt das System aktiv (z. B. drücken Sie Strg-C), wird es automatisch entfernt. Ist dies nicht der Fall (z. B. Stromausfall), wird die Teildatei möglicherweise auf der Zieldiskette unzugänglich gespeichert, sollte jedoch von der nächsten gelöscht werden fsck(die höchstwahrscheinlich beim Neustart automatisch ausgeführt wird, da die Diskette nicht ordnungsgemäß abgemeldet wurde).
Dave Sherohman
50
Falsch. Wenn du dir von einem fs zu einem anderen verschiebst, mv / fs1 / dir / fs2 / und dich unterbrichst, bleibt / fs1 / dir / komplett hier. / fs1 / dir wird nur entfernt, wenn die Verschiebung abgeschlossen ist.
8
user263131 ist richtig. Ausführen strace mv /fs1/dir /fs2/- Das allerletzte, was mv tut, ist, unlinkatalle Quelldateien gleichzeitig aufzurufen (nicht eine nach der anderen, während sie kopiert werden).
Jakob
7
@JJ Sieht so aus, als hätten Sie eine Bash-Erweiterung verwendet. In diesem Fall behandelt mv jede Datei in der Erweiterung als separate Quelle (und nimmt sie somit einzeln vor).
Gkanwar
5
Also ... @bmk oder andere, möchten Sie diese Antwort aktualisieren, um weniger ... falsch zu sein?
Artem Russakovskii
35

Die GNU-Implementierung iteriert über die Argumente in der Befehlszeile, versucht zuerst, sie umzubenennen, und wenn dies fehlschlägt, kopiert sie die Quelle rekursiv und löscht sie dann rekursiv. Damit

mv a b c/

Löschen wird ein vor dem Kopieren b , und startet nicht alles in dem Löschen ein , bevor die Zielkopie abgeschlossen ist.

Beachten Sie, dass dies nur für die GNU-Implementierung gilt.

Zur Verdeutlichung: Wenn a ein Verzeichnis ist, das d und e enthält , und b eine Datei ist, lautet die Reihenfolge

  • schaffen c / a
  • Kopieren Sie a / d -> c / a / d
  • Kopieren Sie a / e -> c / a / e
  • a / d löschen
  • a / e löschen
  • a. löschen
  • Kopie b -> c / b
  • löschen b
Simon Richter
quelle
1
Können Sie eine Quelle dafür bereitstellen? Andere Antworten geben an, dass eine Quelldatei sofort gelöscht wird, nachdem sie in ein anderes Dateisystem kopiert wurde (dh nicht alle kopiert, sondern alle gelöscht).
Jamesbtate
1
Erfahrung. Ich habe ein Beispiel hinzugefügt, um zu verdeutlichen, wie meine und die anderen Antworten übereinstimmen. Wenn Sie nur einzelne Dateien auflisten, wird tatsächlich jede Datei sofort gelöscht.
Simon Richter
Ich beobachte das in dieser Antwort beschriebene Verhalten unter macOS, also auch mit BSD mv, also nicht nur mit GNU.
kirelagin
12

Sie verschieben ein Verzeichnis, unterbrechen das Verschieben und das ursprüngliche Verzeichnis bleibt erhalten:

$ mv a b/

Wenn Sie mehrere Verzeichnisse verschieben, bleibt jedes Verzeichnis entweder an der Quelle oder am Ziel erhalten, je nachdem, wann Sie unterbrochen haben:

$ mv a b c/

Wie ich zu meiner Antwort kam:

$ mv --version
mv (GNU coreutils) 8.21

$ info mv
... It first uses some of the same code that's used by `cp -a'
to copy the requested directories and files, then (assuming the copy
succeeded) it removes the originals.  If the copy fails, then the part
that was copied to the destination partition is removed.  If you were
to copy three directories from one partition to another and the copy of
the first directory succeeded, but the second didn't, the first would
be left on the destination partition and the second and third would be
left on the original partition.

Als Test habe ich einen großen Ordner in ein NFS-Verzeichnis kopiert, unterbrochen, und die Anzahl der Dateien in meinem großen Quellordner blieb gleich, und der Teilinhalt wurde im NFS-Verzeichnis belassen. Ich habe "find. -Type f | wc -l" verwendet, um dies zu überprüfen.

Sieht so aus, als ob Simons Antwort richtig ist.

user79878
quelle
9

Die akzeptierte Antwort ist definitiv falsch, wenn es darum geht, zwischen Dateisystemen zu wechseln - eine Tatsache, die mir schon ein paar Mal große Probleme erspart hat. Wenn Sie ein Verzeichnis verschieben, das Unterverzeichnisse enthält, wird keine Datei in einem Unterverzeichnis gelöscht, bevor das gesamte Unterverzeichnis kopiert wurde. Dies ist übrigens die eigentliche Bedeutung von "Objekt für Objekt" - ein Unterverzeichnis ist ein Objekt (eine Datei), und daher muss seine Integrität durch eine vollständige Kopie am Ziel erhalten bleiben, bevor etwas gelöscht werden kann. Daher erscheint mir die Antwort von Simon als die richtige.

bhak
quelle
4

Nein. Mv arbeitet Objekt für Objekt, sodass Objekte, die bereits verarbeitet wurden, aus der Quelle entfernt werden.

Ignacio Vazquez-Abrams
quelle
2

Auf jeden Fall nein. Die Bewegung erfolgt Objekt für Objekt. Das Objekt, das bis zur Unterbrechungsstelle zum Ziel bewegt wurde, soll daher in der Quelle nicht mehr vorhanden sein.

Wenn mv für eine große Datei (zwischen verschiedenen) ausgegeben wurde und diese unterbrochen wurde, ist die Quelle intakt. Auf dem Ziel sehen Sie eine unvollständige Datei bis zur Unterbrechung.

Sie können die MV jedoch mit demselben Befehl wiederherstellen und der Vorgang wird fortgesetzt.

g24l
quelle
2

Wenn Sie mv unterbrechen möchten, weil Sie die Verbindung zum Terminal trennen möchten, können Sie es einfach in den Hintergrund senden:

* press Ctrl+Z

# bg
# disown
Курочка Ряба
quelle
1
Das ist ein guter Punkt, aber er beantwortet die eigentliche Frage nicht.
Julie Pelletier
1
@ JuliePelletier, aber das ist, wonach ich gesucht habe, damit jemand daran interessiert sein kann.
Курочка Ряба