it-swarm.com.de

Liste der Dateien kopieren

Ich habe eine Liste von Dateien, die durch Leerzeichen in einer Datei list.txt getrennt sind. Ich möchte sie in einen neuen Ordner kopieren.

Ich habe versucht zu tun:

cp `cat list.txt` new_folder

aber es hat nicht funktioniert.

Wie würdest du das machen?

Update:

Vielen Dank für all Ihre sehr interessanten Antworten. Ich habe nicht so viel verlangt :)

Nachdem Sie die Lösung ein zweites Mal ausprobiert haben, hat cp anscheinend die Verwendungshilfe gedruckt, da der Ordner new_folder noch nicht existiert hat! Sorry, es scheint ein dummer Fehler zu sein ... Wenn ich den Ordner vorher erstelle, funktioniert es.

Ich habe jedoch viel aus all Ihren Antworten und Lösungen gelernt. Vielen Dank, dass Sie sich die Zeit genommen haben, diese zu schreiben.

31
Klaus

Versuchen Sie es mit xargs:

cat list.txt | xargs -J % cp % new_folder

Update:

Ich habe dies unter OS X gemacht, das eine andere Version als GNU/Linux-Versionen hat. Die xargs, die aus GNU-Findutils stammt, hat keinen -J, aber einen -I, der ähnlich ist (wie Dennis Williamson in einem Kommentar hervorhob). Die OS X-Version von xargs hat sowohl -I als auch -J, die sich geringfügig unterscheiden. Beide funktionieren für diese ursprüngliche Frage.

$ cat list.txt
one
two.txt
three.rtf

$ cat list.txt | xargs -J % echo cp % new_folder
cp one two.txt three.rtf new_folder

$ cat list.txt | xargs -I % echo cp % new_folder
cp one new_folder
cp two.txt new_folder
cp three.rtf new_folder
33
Doug Harris

cat wird überhaupt nicht benötigt:

xargs -a list.txt cp -t new_folder

Oder mit langen Optionen:

xargs --arg-file=list.txt cp --target-directory=new_folder

Hier sind einige Shell-Versionen. Beachten Sie, dass einige Variablen nicht in Anführungszeichen gesetzt sind oder for-Schleifen speziell verwendet werden, da das OP angibt, dass die Dateinamen durch Leerzeichen getrennt sind. Einige dieser Techniken funktionieren nicht bei der Eingabe von Dateinamen pro Zeile, bei der Dateinamen Leerzeichen enthalten.

Bash:

for file in $(<list.txt); do cp "$file" new_folder; done

oder

cp $(<list.txt) new_folder

sh (oder Bash):

# still no cat!
while read -r line; do for file in $line; do cp "$file" new_folder; done; done < list.txt

oder

# none here either
while read -r line; do cp $line new_folder; done < list.txt

oder

# meow
for file in $(cat list.txt); do cp "$file" new_folder; done

oder

# meow
cp $(cat list.txt) new_folder
49

Ich hatte hier früher eine peinlich runde Antwort, aber Denis 'Antwort erinnerte mich daran, dass ich das Grundlegendste verpasst hatte. Also habe ich meine ursprüngliche Antwort gelöscht. Aber da niemandsagtediese sehr grundlegende Sache hat, denke ich, dass es sich lohnt, sie hier zu platzieren.

Die ursprüngliche Frage lautet: "Ich habe eine Textdatei mit einer Liste von durch Leerzeichen getrennten Dateinamen. Wie kann ich diese in ein Zielverzeichnis kopieren?" Auf den ersten Blick mag dies schwierig oder kompliziert erscheinen, da Sie denken, dass Sie die Elemente auf eine bestimmte Weise aus der Datei extrahieren müssen. Wenn die Shell jedoch eine Befehlszeile verarbeitet, ist das erste, was sie tut,die Argumentliste in Token zu unterteilenund (hier ist das Bit, das niemand direkt gesagt hat)Leerzeichen getrennte Token. (Neue Zeilen trennen auch Token, weshalb Doug Harris 'Test mit einer durch neue Zeilen getrennten Liste dasselbe Ergebnis lieferte.) Das heißt, die Shell erwartet und kann bereits mit einer durch Leerzeichen getrennten Liste umgehen.

Alles, was Sie hier tun müssen, ist, die durch Leerzeichen getrennte Liste (die Sie bereits haben) an die richtige Stelle in Ihrem Befehl zu setzen. Ihr Befehl ist eine Variation davon:

cp file1 file2 file3...file# target

Der einzige Nachteil ist, dass Sie die Liste der Dateien 1 bis # aus Ihrer Textdatei abrufen möchten.

Wie Dennis in seinem Kommentar betont, sollte Ihr ursprünglicher Versuch (cpcat list.txtnew_folder) bereits funktioniert haben. Warum? Da der interne Befehl cat list.txt zuerst von der Shell verarbeitet und zu file1 file2 file3...file# erweitert wird, erwartet und erwartet die Shell genau diesen Teil des Befehls. Wenn es nicht geklappt hat, waren entweder (1) Sie einen Tippfehler oder (2) Ihre Dateinamen irgendwie seltsam (sie hatten Leerzeichen oder andere ungewöhnliche Zeichen).

Der Grund, warum alle Antworten von Dennis funktionieren, besteht einfach darin, dass sie die erforderliche Liste von Dateien für cp bereitstellen und diese Liste dort platzieren, wo sie im gesamten Befehl enthalten ist. Der Befehl selbst ist wiederum folgendermaßen aufgebaut:

cp list-of-files target_directory

Es ist leicht zu sehen, wie das alles in dieser Version zusammenkommt:

cp $(<list.txt) new_folder

$() veranlasst die Shell, den Befehl in Klammern auszuführen und die Ausgabe an diesem Punkt in der größeren Zeile zu ersetzen. Dann führt die Shell die gesamte Linie aus. Übrigens ist $() eine modernere Version dessen, was Sie bereits mit Backticks gemacht haben (`). Weiter: < ist ein Dateiumleitungsoperator. Sie weist die Shell an, den Inhalt von list.txt auf die Standardeingabe zu übertragen. Da das $()-Bit zuerst verarbeitet wird, geschieht Folgendes schrittweise:

  1. cp $(<list.txt) new_folder# split line into three tokens: cp, $(<list.txt), new_folder
  2. cp file1 file2 file3...file# new_folder# substitute result of $(<list.txt) into the larger command

Offensichtlich ist Schritt 2 einfach der normale cp Befehl, den Sie wollten.

Mir ist klar, dass ich dieses (vielleicht sehr tote) Pferd sehr oft besiege, aber ich denke, es lohnt sich, es zu tun. Das Verstehen vongenau, wie die Shell einen Befehl verarbeitet, kann Ihnen helfen, ihn besser zu schreiben und viel zu vereinfachen. Es zeigt Ihnen auch, wo sich Probleme wahrscheinlich verstecken. In diesem Fall hätte meine erste Frage an Sie zum Beispiel nach lustigen Dateinamen oder einem möglichen Tippfehler lauten sollen. Akrobatik war nicht erforderlich.

7
Telemachus