Ich habe eine Liste von Dateinamen in einer Datei namens list_of_files.txt
.
Ich möchte den Inhalt jeder Datei in dieser Liste in eine andere Datei mit dem Namen kopieren all_compounds.sdf
.
Wie soll ich das von der Kommandozeile aus machen?
Ich habe eine Liste von Dateinamen in einer Datei namens list_of_files.txt
.
Ich möchte den Inhalt jeder Datei in dieser Liste in eine andere Datei mit dem Namen kopieren all_compounds.sdf
.
Wie soll ich das von der Kommandozeile aus machen?
Antworten:
Verwenden Sie keine einfache Befehlsersetzung, um Dateinamen abzurufen (dies kann leicht zu Leerzeichen und anderen Sonderzeichen führen). Verwenden Sie etwas wie xargs
:
xargs -d '\n' -a list_of_files.txt cat > all_compounds.sdf
Oder eine while read
Schleife:
while IFS= read -r file; do cat "$file"; done < list_of_files.txt > all_compounds.sdf
Um die Befehlsersetzung sicher zu verwenden, stellen Sie mindestens IFS
nur die Zeilenumbrüche ein und deaktivieren Sie das Globbing (Platzhaltererweiterung):
(set -f; IFS=$'\n'; cat $(cat list_of_files.txt) > all_compounds.sdf)
Die umgebenden Klammern ()
sollen dies in einer Subshell ausführen, damit Ihre aktuelle Shell von diesen Änderungen nicht betroffen ist.
Schnell und dreckig unterwegs ...
cat $(cat list_of_files.txt) >> all_compounds.sdf
Bitte beachten Sie: Dies funktioniert nur, wenn sich die Dateinamen in Ihrer Liste sehr gut verhalten. Wenn Leerzeichen, Zeilenumbrüche oder Zeichen mit besonderer Bedeutung für die Shell auftauchen, kann es zu Fehlern kommen. Verwenden Sie stattdessen diese Antwort, um zuverlässige Ergebnisse zu erhalten.
cat
con cat enates files. Es druckt auch deren Inhalt.command2 $(command1)
können Sie die Ausgabe von command1
( cat list...
) an command2
( cat
) übergeben, die die Dateien verkettet.Verwenden Sie dann die Umleitung >>
, um die Ausgabe an eine Datei zu senden, anstatt an stdout zu drucken. Wenn Sie die Ausgabe sehen möchten, verwenden Sie tee
stattdessen:
cat $(cat list_of_files.txt) | tee -a all_compounds.sdf
(Ich habe >>
anstelle von >
und tee
mit dem -a
Schalter verwendet, falls Ihre Datei bereits vorhanden ist. Dies wird an die Datei angehängt , anstatt sie zu überschreiben, falls sie bereits vorhanden ist.)
cat
wird die gesamte Liste als ein Argument abgerufen .
Während GNU awk
ein Textverarbeitungsprogramm ist, können externe Shell-Befehle über einen system()
Aufruf ausgeführt werden. Das können wir so zu unserem Vorteil nutzen:
$ awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt
Die Idee hier ist einfach: Wir lesen die Datei Zeile für Zeile und erstellen aus jeder Zeile eine formatierte Zeichenfolge cat "File name.txt"
, die dann an übergeben wird system()
.
Und hier ist es in Aktion:
$ ls
file1.txt file2.txt file3 with space.txt file_list.txt
$ awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt
Hi, I'm file2
Hi, I'm file1
Hi, I'm file3
Wir haben dort also schon den größten Teil der Aufgabe erledigt - wir haben alle Dateien auf der Liste gedruckt. Der Rest ist einfach: Leiten Sie die endgültige Ausgabe in die Datei mit dem >
Operator in die Zusammenfassungsdatei um.
awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt > output.txt
"$(cat list_of_files.txt)"