Ich habe Millionen von Bildern auf meinem Ubuntu-Cloud-Server. Wenn ich mit dem mv
Befehl einen vollständigen Ordner mit 12 Millionen Bildern verschiebe , geschieht dies fast augenblicklich. Allerdings, wenn ich mv
nur Bilder (nicht den Ordner) dann dauert es einige Zeit. Gibt es eine Möglichkeit, alle Bilder so schnell wie Ordner zu verschieben?
Folgendes passiert gerade:
src ordner hat 12 millionen bilder und ich verschiebe diese in den dst ordner mit
$ mv src ../dst
Passiert sofort
Im src-Ordner gehe ich folgendermaßen vor, um:
find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ {} +
Dies dauert einige Zeit.
Gibt es eine Möglichkeit, den zweiten Prozess zu beschleunigen?
dst
in einer Partition, wohingegen../../dst
sich auf einer anderen befindet.{}
Argument, in dem die Dateinamen erweitert würden.find
.find ... -exec mv -t ../../dst/ {} \;
würdemv
einmal pro Datei anrufen ;find ... -exec mv -t ../../dest {} +
Es wäre viel schneller, so viele Dateien wie möglich pro Aufruf zu kopieren, aber immer noch nicht so schnell, wie das von dadexix86 erklärte Verzeichnis selbst zu verschieben .Antworten:
TL; DR : Nein
Für eine kleinere Anzahl von Dateien würden Sie
find
aber auch in diesem vereinfachten und kleineren Fall nicht brauchen , wenn Sie nurEs dauert länger, als das gesamte Verzeichnis auf einmal zu verschieben.
Warum? Der Punkt ist zu verstehen, was
mv
tut.Verschiebt kurz gesagt
mv
eine Zahl (die ein Verzeichnis oder eine Datei kennzeichnet) von einem Inode (dem Verzeichnis, in dem sie enthalten ist) in einen anderen, und diese Indizes werden im Journal des Dateisystems oder in der FAT (falls das Dateisystem) aktualisiert ist so implementiert).Befinden sich Quelle und Ziel im selben Dateisystem, gibt es keine tatsächliche Datenverschiebung. Sie ändert lediglich die Position und den Punkt, an dem sie angehängt sind.
Wenn Sie also
mv
ein Verzeichnis haben, führen Sie diesen Vorgang einmal aus .Wenn Sie jedoch 1 Million Dateien verschieben, führen Sie diesen Vorgang 1 Million Mal durch .
Um Ihnen ein praktisches Beispiel zu geben: Sie haben einen Baum mit vielen Ästen. Insbesondere gibt es einen Knoten, an den 1 Million Zweige angeschlossen sind.
Um diese Zweige abzuschneiden und an einen anderen Ort zu verschieben, können Sie sie entweder einzeln abschneiden, sodass Sie 1 Million Schnitte ausführen, oder Sie schneiden direkt vor dem Knoten, sodass Sie nur einen Schnitt ausführen (dies ist der Unterschied zwischen dem Verschieben der Dateien und das Verzeichnis).
quelle
mv
in demselben Dateisystem nur ein Umschreiben des Inhaltsverzeichniseintrags ist.mv *.jpg
dürfte bei 12 Millionen Dateien scheitern, weshalb er find verwendet. Die meisten Unixe, einschließlich Linux, haben meines Erachtens (es sei denn, jemand hat sie in den letzten 5 bis 10 Jahren geändert) eine begrenzte maximale Länge der Befehlszeile. Ich denke, es war lange Zeit 64K für Linux. Die gleiche Grenze gilt für Umgebungsvariablen, da bin ich mir ziemlich sicher.Es wird immer noch langsam sein, da das Dateisystem, wie bereits erwähnt, jeden Dateinamen an seinen neuen Speicherort verlinken muss.
Sie können es jedoch von dem, was Sie jetzt haben, beschleunigen.
Ihr Suchbefehl führt die Ausführung für jede Datei einmal aus. So wird der
mv
Befehl 12 Millionen Mal für 12 Millionen Dateien gestartet. Dies kann auf zwei Arten verbessert werden.Fügen Sie am Ende ein Pluszeichen hinzu:
find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ +
Überprüfen Sie die Manpage, um sicherzustellen, dass sie in Ihrer Version von unterstützt wird
find
. Der Effekt sollte darin bestehen, eine Reihe vonmv
Befehlen mit so vielen Dateinamen auszuführen, wie auf jede Befehlszeile passen.Verwenden Sie
find
undxargs
zusammen.find -maxdepth 1 -name '*.jpg' -print0 | xargs -0 mv -t ../../dst/
Das
-print0
wird NUL, auch bekannt als Null-Byte, verwenden, um die Dateinamen zu trennen. Dieses Plusxargs -0
behebt alle Probleme,xargs
die ansonsten mit Leerzeichen in Dateinamen auftreten könnten. Derxargs
Befehl liest die Liste der Dateinamen aus demfind
Befehl und führt denmv
Befehl für so viele Dateinamen aus, wie passen.quelle
Ihre Verwirrung rührt von der Dateisystemabstraktion her, die Sie glauben lässt, dass ein Ordner Dateien und andere Ordner in einer baumartigen Weise enthält. Dies ist jedoch nicht der Fall: Alle Dateien und Verzeichnisse in einem Dateisystem befinden sich auf derselben Ebene und werden abhängig von der Implementierung mit einer Reihe von Nummern gekennzeichnet. Verzeichnisse sind nur spezielle Dateien, die Listen anderer Dateien enthalten.
Wenn Sie Dateien in einem Dateisystem "verschieben", werden die eigentlichen Dateien nirgendwo abgelegt. Stattdessen werden Listen in Verzeichnissen aktualisiert, um die Änderung widerzuspiegeln.
mv src ../dst
Verschiebt einen einzelnen Listeneintrag von Verzeichnis.
zu Verzeichnis../dst
, so ist es schnell.find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/
muss Millionen von Einträgen verschieben, also ist es langsamer. Es kann möglicherweise beschleunigt werden, wenn Siemv
nur einmal und nicht einmal pro Datei aufrufen , und dermv
Befehl selbst kann so optimiert werden, dass mehrere Verzeichniseinträge in einem Schritt verschoben werden. Es gibt jedoch keine Möglichkeit, ihn so schnell wie beim Verschieben eines einzelnen Verzeichnisses zu gestalten .quelle
Eine vereinfachte Antwort
Das Verschieben einer Datei erfolgt in 3 Schritten:
Dieser Vorgang ist für eine Datei oder einen Ordner identisch.
und offensichtlich ist dies für 1 Datei 100 schneller als für 100 Dateien.
man link
is the add ()man unlink
is the remove () verwendetmv
nur die beiden obigen Befehle und fügt eine dazwischen liegende Prüfung hinzu, um Datenverlust zu vermeiden.quelle