Kopieren einer großen Anzahl von Dateien von einem Verzeichnis in ein anderes unter Linux
Ich habe ein Verzeichnis mit rund 280.000 Dateien. Ich möchte sie in ein anderes Verzeichnis verschieben.
Wenn ich cp
oder mv
verwende, wird die Fehlermeldung 'Argumentliste zu lang'angezeigt.
Wenn ich ein Skript wie
for file in ls *; do
cp {source} to {destination}
done
Dann verschlechtert sich aufgrund des Befehls ls
seine Leistung.
Wie kann ich das tun?
9 answers
Verwenden Sie rsync:
$ rsync -a {source}/ {destination}/
Z. B.
$ rsync -a /some/path/to/src/ /other/path/to/dest/
(beachten Sie die Trailing /s)
Hinweis: Wenn es sich um einen langwierigen Vorgang handelt und Sie beim Kopieren einen Hinweis auf den Fortschritt sehen möchten, können Sie entweder die Option
-v
(ausführlich) hinzufügen, die dann jede zu kopierende Datei auflistet, oder die Option --progress
verwenden, um eine prägnantere Fortschrittsausgabe zu erhalten.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2018-04-20 13:04:26
Ich vermisse zwei Wendungen in den Antworten hier, also füge ich noch einen hinzu.
Obwohl dies mich daran erinnert, eine weitere Standardantwort hinzuzufügen...
Hier gibt es zwei Probleme:
Ich habe ein Verzeichnis mit rund 280.000 Dateien.
Die meisten Tools skalieren nicht so gut mit dieser Anzahl von Dateien. Nicht nur die meisten Linux-Tools oder Windows-Tools, sondern auch viele Programme. Und das könnte beinhalten ihr Dateisystem. Die langfristige Lösung wäre "nun, mach das dann nicht". Wenn Sie verschiedene Dateien haben, aber sie in verschiedenen Verzeichnissen. Wenn nicht erwarten, in Zukunft auf Probleme zu stoßen.
Nachdem wir das gesagt haben, gehen wir zu Ihrem eigentlichen Problem über:
Wenn ich cp oder mv verwende, wird die Fehlermeldung 'Argumentliste zu lang'
Dies wird durch die Erweiterung von * durch die Shell verursacht. Die Shell hat nur begrenzten Platz für das Ergebnis und es läuft aus. Dies bedeutet jede befehl mit einem von der Shell erweiterten *
wird auf dasselbe Problem stoßen. Sie müssen entweder weniger Optionen gleichzeitig erweitern oder einen anderen Befehl verwenden.
Ein alternativer Befehl, der häufig verwendet wird, wenn Sie auf dieses Problem stoßen, ist find
. Es gibt bereits mehrere Antworten, die zeigen, wie man es benutzt, also werde ich das alles nicht wiederholen. Ich werde jedoch auf den Unterschied zwischen \;
und +
hinweisen, da dies einen großen Leistungsunterschied machen und sich gut in die vorherige Erweiterungserklärung.
find /path/to/search --name "*.txt" -exec command {} \;
Findet alle Dateien unter path/to/search/ und gibt einen Befehl damit aus, aber beachte die Anführungszeichen um *
. Das füttert das * mit dem Befehl. Wenn wir es nicht kapseln oder entkommen würden, würde die Shell versuchen, es zu erweitern, und wir würden den gleichen Fehler erhalten.
Schließlich möchte ich etwas über {} erwähnen. Diese Klammern werden durch den von find gefundenen Inhalt ersetzt. Wenn Sie den Befehl mit einem Semikolom ;
(eines, das Sie müssen aus der Shell entkommen, daher die \;
' s in den Beispielen) dann werden die Ergebnisse einzeln übergeben. Dies bedeutet, dass Sie 280000 mv-Befehle ausführen. Eine für jede Datei. Dies könnte langsam sein.
Alternativ können Sie mit +
. Dies wird so viele Argumente wie möglich gleichzeitig übergeben. Wenn bash 2000 Argumente verarbeiten kann, dann find / path-name "*filetype " - exec some_move {}+ ruft den Befehl some_move ungefähr 140 Mal auf, jedes Mal mit 2000 Argumenten. Das ist mehr effizient (lesen: schneller).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2016-11-22 19:24:59
Wie wäre es beim Verschieben (anstatt zu kopieren):
$ find {origin}/ -maxdepth 1 -name "*" -o -name ".*" -exec mv '{}' {destination}/ ';'
Ich denke, das wird die Struktur (Unterverzeichnisse) und versteckte Dateien oder Verzeichnisse verschieben, plus kein zusätzlicher Speicherplatz wie bei rsync + rm. Und wenn sich {origin} und {destination} in derselben Partition befinden, ist es schneller.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2012-05-08 02:50:20
Sie brauchen das ls nicht, Sie können einfach
for file in *; do
cp $file /your/dest
done
, Oder Sie können etwas tun wie:
echo * | xargs -i cp {} /your/dest
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2010-02-10 14:20:43
#!/bin/bash
d=$(date +%Y%m%d%H%m%s)
cd /path
tar zcvf "/destination/bakup_${d}.tar.gz" mydirectory_for_transer
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2010-02-10 14:25:45
Angenommen, Sie möchten die Dateien innerhalb desselben Dateisystems verschieben, können Sie einfach das Verzeichnis mit Ihren Lacs umbenennen und damit fertig sein.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2010-06-14 23:28:11
Ich mag rsync
dafür oder:
find dir1 -type f -exec cp {} dir2 \;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2011-05-11 07:19:34
Mit tar:
(cd {origin}; tar cf - .)|(cd {destination}; tar xvf -)
Funktioniert, um die Dinge zu beginnen, wenn der Ursprung anfangs zu groß für rsync ist, die Deltas jedoch nicht.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2015-11-04 22:35:36
In meinem Fall waren sowohl cp
als auch rsync
viel zu langsam, um etwa 4 Millionen Dateien von einer Festplatte auf eine SSD zu kopieren .txt-Dateien im selben Ordner, so passen Sie Ihre find
zu Ihnen passen):
cd /path/to/source/folder
find . -name '*.txt' -print >/tmp/test.manifest
tar -c -T /tmp/test.manifest | (cd /path/to/destination/folder; tar xfp -)
Ich musste die Dateinamen in eine temporäre Datei drucken, weil ich den Fehler Argument list too long
. Die Verwendung von tar
hat meine Übertragungsgeschwindigkeiten erheblich verbessert, obwohl ich davon ausgehen kann, dass Dateien, die weniger leicht komprimiert werden können, möglicherweise nicht so gut funktionieren.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2016-11-16 17:15:10