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 readciclo:
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 IFSsolo 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)
catcon 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 teeinvece:
cat $(cat list_of_files.txt) | tee -a all_compounds.sdf(Ho usato >>invece >e teecon l' -aopzione nel caso in cui il tuo file esista già - questo si aggiunge al file invece di sovrascriverlo, se esiste già)
catottiene 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)"