Come copio il contenuto di ogni file in un elenco in un altro file?


15

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:


20

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.


14

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)

Appunti

  • catcon cat enate i file. Stampa anche il loro contenuto.
  • Usando la sostituzione dei comandi 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à)


1
@Zanna cita le sostituzioni di comando per evitare la divisione delle parole, come"$(cat list_of_files.txt)"
Sergiy Kolodyazhnyy,

4
@Serg se la divisione delle parole non viene eseguita, catottiene l'intero elenco come argomento.
Muru,

@muru OK, come gestiamo i nomi dei file che contengono spazi?
Sergiy Kolodyazhnyy,

1
@Serg ha impostato IFS di conseguenza - vedi l'ultimo paragrafo della mia risposta
muru

4

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.