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?

Author: tripleee, 2010-02-10

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.
 22
Author: Paul R,
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...

geben Sie hier die Bildbeschreibung ein

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

 11
Author: Hennes,
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.

 2
Author: jaimealsilva,
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
 1
Author: wich,
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
 0
Author: user31894,
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.

 0
Author: Tobu,
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 \;
 0
Author: Gaff,
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.

 0
Author: James McGill,
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.

 0
Author: Kelly,
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