Ho un elenco di nomi di file all'interno di un file chiamato list_of_files.txt
.
Voglio copiare il contenuto di ciascun file in quell'elenco in un altro file chiamato all_compounds.sdf
.
Come dovrei farlo dalla riga di comando?
Ho un elenco di nomi di file all'interno di un file chiamato list_of_files.txt
.
Voglio copiare il contenuto di ciascun file in quell'elenco in un altro file chiamato all_compounds.sdf
.
Come dovrei farlo dalla riga di comando?
Risposte:
Non utilizzare la semplice sostituzione di comando per ottenere nomi di file (che potrebbero facilmente rompersi con spazi e altri caratteri speciali). Usa qualcosa come xargs
:
xargs -d '\n' -a list_of_files.txt cat > all_compounds.sdf
O un while read
ciclo:
while IFS= read -r file; do cat "$file"; done < list_of_files.txt > all_compounds.sdf
Per utilizzare la sostituzione dei comandi in modo sicuro, almeno impostare IFS
solo la nuova riga e disabilitare il globbing (espansione con caratteri jolly):
(set -f; IFS=$'\n'; cat $(cat list_of_files.txt) > all_compounds.sdf)
Le parentesi circostanti ()
devono eseguirlo in una subshell, in modo che la shell corrente non sia influenzata da queste modifiche.
Modo rapido e sporco ...
cat $(cat list_of_files.txt) >> all_compounds.sdf
Nota: questo funziona solo se i nomi dei file nella tua lista sono molto ben educati - le cose andranno male se hanno spazi, righe o caratteri che hanno un significato speciale per la shell - usa invece questa risposta per risultati affidabili)
cat
con cat enate i file. Stampa anche il loro contenuto.command2 $(command1)
è possibile passare l'output di command1
( cat list...
) a command2
( cat
) che concatena i file.Quindi utilizzare il reindirizzamento >>
per inviare l'output a un file anziché stamparlo su stdout. Se vuoi vedere l'output, usa tee
invece:
cat $(cat list_of_files.txt) | tee -a all_compounds.sdf
(Ho usato >>
invece >
e tee
con l' -a
opzione nel caso in cui il tuo file esista già - questo si aggiunge al file invece di sovrascriverlo, se esiste già)
cat
ottiene l'intero elenco come argomento.
Mentre GNU awk
è un'utilità di elaborazione del testo, consente di eseguire comandi di shell esterni tramite system()
chiamata. Possiamo utilizzarlo a nostro vantaggio in questo modo:
$ awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt
L'idea qui è semplice: leggiamo il file riga per riga e da ogni riga creiamo una stringa formattata cat "File name.txt"
, che viene quindi passata a system()
.
Ed eccolo in azione:
$ 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
Quindi abbiamo già svolto gran parte dell'attività, abbiamo stampato tutti i file nell'elenco. Il resto è semplice: reindirizzare l'output finale su file con >
operatore nel file di riepilogo.
awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt > output.txt
"$(cat list_of_files.txt)"