Ich habe eine Liste von Dateien, die durch Leerzeichen in einer Datei getrennt sind list.txt
. 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?
Aktualisieren:
Vielen Dank für all Ihre sehr interessanten Antworten. Ich habe nicht so viel verlangt :)
Nachdem Sie die oben genannte Lösung ein zweites Mal ausprobiert haben, scheint cp
die Verwendungshilfe gedruckt worden zu sein, da der Ordner new_folder
noch nicht vorhanden war! Entschuldigung, es scheint ein dummer Fehler zu sein ... Wenn ich den Ordner vorher erstelle, funktioniert es.
Ich habe jedoch aus all Ihren Antworten und Lösungen viel gelernt. Vielen Dank, dass Sie sich die Zeit genommen haben, diese zu schreiben.
Antworten:
Versuchen Sie es mit xargs:
Aktualisieren:
Ich habe dies unter OS X gemacht, das eine andere Version als GNU / Linux-Versionen hat. Das,
xargs
was von GNU kommt, hat findutils nicht,-J
aber es hat,-I
was ähnlich ist (wie Dennis Williamson in einem Kommentar hervorhob ). Die OS X-Version von xargs hat beide-I
und-J
ein leicht unterschiedliches Verhalten - beide funktionieren für diese ursprüngliche Frage.quelle
xargs
hat nicht-J
hat ,-I
die die gleiche Sache zu tun scheint. Welche Version vonxargs
und welches Betriebssystem / welche Distribution haben Sie?xargs --version
gibt eine Verwendungsfehlermeldung zurück. Es ist wahrscheinlich eine BSD-Version von xargs. Die Verwendung von-I
und unterscheiden-J
sich geringfügig. Ich werde meine Antwort mit gut formatierten Beispielen aktualisieren.-J
und-I
:)Überhaupt nicht nötig
cat
:Oder mit langen Optionen:
Hier sind einige Shell-Versionen. Beachten Sie, dass einige Variablen nicht in Anführungszeichen gesetzt sind oder
for
Schleifen 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:
oder
sh (oder Bash):
oder
oder
oder
quelle
-t
gebrauchtxargs -a list.txt cp -t new_folder
?-t
ist eine Option voncp
. Es kopiert alle Quellargumente in das angegebene Zielverzeichnis. Hier kann das Ziel vor der Quelle angegeben werden, die durch denxargs
Befehl hinzugefügt wird .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 niemand diese sehr grundlegende Sache gesagt 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, teilt sie die Argumentliste zunächst in Token und (hier ist das Bit, das niemand direkt gesagt hat) Leerzeichen in Token auf . (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 eine durch Leerzeichen getrennte Liste verarbeiten.
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:
Der einzige Nachteil ist, dass Sie die Liste der Dateien 1 bis # aus Ihrer Textdatei abrufen möchten.
Wie Dennis in seinem Kommentar
cp
betont , hätte Ihr ursprünglicher Versuch ( cat list.txtnew_folder
) bereits funktionieren müssen. Warum? Denn der interne Befehlcat list.txt
wird zuerst von der Shell verarbeitet und erweitert.file1 file2 file3...file#
Genau das erwartet und wünscht sich die Shell in diesem 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
die Bearbeitung bereitstellen und diese Liste dort platzieren, wo sie in den gesamten Befehl gehört. Der Befehl selbst ist wiederum folgendermaßen aufgebaut:Es ist leicht zu sehen, wie das alles in dieser Version zusammenkommt:
$()
Bewirkt, dass die Shell den Befehl in Klammern ausführt und die Ausgabe an dieser Stelle in der größeren Zeile ersetzt. Dann führt die Shell die gesamte Linie aus. Übrigens$()
ist eine modernere Version dessen, was Sie bereits mit Backticks gemacht haben (`). Next:<
ist ein Dateiumleitungsoperator. Es weist die Shell an, den Inhalt derlist.txt
Standardeingabe zu sichern. Da das$()
Bit zuerst verarbeitet wird, geschieht Folgendes schrittweise:cp $(<list.txt) new_folder
# split line into three tokens: cp, $(<list.txt), new_folder
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, dass es sich lohnt, es zu tun. Wenn Sie genau wissen , wie die Shell einen Befehl verarbeitet, können Sie ihn besser schreiben und erheblich 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.
quelle
--parents
Flag. Sie können eine ausführliche-v
Aufzeichnung darüber erstellen, was kopiert wurde. Wenn Sie Berechtigungen behalten möchten, benötigen Sie das Flag-a
oder-p
. Dhcp --parents -av $(<list.txt) new_folder
. Dies alles unter der-r
Voraussetzung, dass Ihre Dateiliste wirklich alle Dateien enthält. Andernfalls benötigen Sie möglicherweise auch das Flag, um eine Rekursion durchzuführen.--parents
gibt es die Flagge dort nicht. Ihre (von BSD abgeleitete) Versioncp
bietet nur kurze Optionen, keine langen Optionen im GNU-Stil. Bei einem BSD-Stilcp
ist das Flag für rekursives Kopieren Großbuchstaben-R
und nicht Kleinbuchstaben.