Tengo una lista de nombres de archivo dentro de un archivo llamado list_of_files.txt
.
Quiero copiar el contenido de cada archivo en esa lista en otro archivo llamado all_compounds.sdf
.
¿Cómo debo hacer esto desde la línea de comando?
Tengo una lista de nombres de archivo dentro de un archivo llamado list_of_files.txt
.
Quiero copiar el contenido de cada archivo en esa lista en otro archivo llamado all_compounds.sdf
.
¿Cómo debo hacer esto desde la línea de comando?
Respuestas:
No use la simple sustitución de comandos para obtener nombres de archivo (que podrían romperse fácilmente con espacios y otros caracteres especiales). Use algo como xargs
:
xargs -d '\n' -a list_of_files.txt cat > all_compounds.sdf
O un while read
bucle:
while IFS= read -r file; do cat "$file"; done < list_of_files.txt > all_compounds.sdf
Para utilizar la sustitución de comandos de forma segura, al menos establezca IFS
solo la nueva línea y desactive el globbing (expansión de comodines):
(set -f; IFS=$'\n'; cat $(cat list_of_files.txt) > all_compounds.sdf)
Los paréntesis circundantes ()
deben ejecutar esto en una subshell, para que su shell actual no se vea afectado por estos cambios.
De manera rápida y sucia ...
cat $(cat list_of_files.txt) >> all_compounds.sdf
Tenga en cuenta: esto solo funciona si los nombres de archivo en su lista se comportan muy bien; las cosas saldrán mal si tienen espacios, líneas nuevas o cualquier carácter que tenga un significado especial para el shell; use esta respuesta para obtener resultados confiables)
cat
con cat enates archivos. También imprime sus contenidos.command2 $(command1)
, puede pasar la salida de command1
( cat list...
) a command2
( cat
) que concatena los archivos.Luego use la redirección >>
para enviar el resultado a un archivo en lugar de imprimirlo en stdout. Si desea ver la salida, use tee
en su lugar:
cat $(cat list_of_files.txt) | tee -a all_compounds.sdf
(He utilizado en >>
lugar de >
y tee
con el -a
interruptor en caso de que su archivo ya exista; esto se agrega al archivo en lugar de sobrescribirlo, si ya existe)
cat
obtiene la lista completa como un argumento.
Si bien GNU awk
es una utilidad de procesamiento de texto, permite ejecutar comandos de shell externos a través de una system()
llamada. Podemos utilizar eso para nuestra ventaja así:
$ awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt
La idea aquí es simple: leemos el archivo línea por línea, y de cada línea creamos una cadena formateada cat "File name.txt"
, que luego se pasa asystem()
.
Y aquí está en acción:
$ 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
Ya hemos hecho la mayor parte de la tarea allí: imprimimos todos los archivos de la lista. El resto es simple: redirija la salida final al archivo con el >
operador en el archivo de resumen.
awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt > output.txt
"$(cat list_of_files.txt)"