Cómo agregar contenido de varios archivos en un solo archivo

174

Quiero copiar el contenido de cinco archivos en un archivo tal como está. Intenté hacerlo usando cp para cada archivo. Pero eso sobrescribe el contenido copiado del archivo anterior. También intenté

paste -d "\n" 1.txt 0.txt

Y no funcionó.

Quiero que mi script agregue la nueva línea al final de cada archivo de texto.

p.ej. Archivos 1.txt, 2.txt, 3.txt. Poner contenidos de 1,2,3 en 0.txt

Cómo lo hago ?

Vapor
fuente
1
posible duplicado de archivos
Nikos C.
Otra respuesta aquí: stackoverflow.com/questions/2576693/…
Nikos C.

Respuestas:

308

Necesita el catcomando (abreviatura para concatenar), con redirección de shell ( >) en su archivo de salida

cat 1.txt 2.txt 3.txt > 0.txt
radical7
fuente
8
debería ser >> ¿verdad? y también ¿por qué hay una nueva línea antes de todo el texto en mi archivo 0.txt?
Steam
1
¿Querías preservar el contenido de 0.txt?
sehe
13
@blasto depende. Se usaría >>para agregar un archivo a otro, donde se > sobrescribe el archivo de salida con lo que se le haya dirigido. En cuanto a la nueva línea, ¿hay una nueva línea como primer carácter en el archivo 1.txt? Puedes averiguarlo usando od -cy viendo si el primer personaje es un \n.
radical7
1
@ radical7 Gracias. En realidad, mis archivos son como foo_1, foo_2, foo_3. Traté de modificar su código como - cat "$ filename _" {1,2,3} ". Txt", pero no funcionó.
Steam
1
@blasto Definitivamente vas en la dirección correcta. Bash ciertamente acepta el formulario {...}para la coincidencia de nombre de archivo, ¿entonces quizás las citas estropearon un poco las cosas en su script? Siempre trato de trabajar con cosas como esta usando lsun shell. Cuando obtengo el comando correcto, simplemente lo corto y lo pego en un script tal como está. También puede encontrar la -xopción útil en sus scripts: hará eco de los comandos expandidos en el script antes de la ejecución.
radical7
97

Otra opción, para aquellos de ustedes que todavía se encuentran con esta publicación como lo hice, es usar find -exec:

find . -type f -name '*.txt' -exec cat {} + >> output.file

En mi caso, necesitaba una opción más sólida que buscara en varios subdirectorios, así que decidí usarla find. Desglosándolo:

find .

Mire dentro del directorio de trabajo actual.

-type f

Solo interesado en archivos, no directorios, etc.

-name '*.txt'

Reduzca el conjunto de resultados por nombre

-exec cat {} +

Ejecute el comando cat para cada resultado. "+" significa que solo catse genera 1 instancia de (thx @gniourf_gniourf)

 >> output.file

Como se explica en otras respuestas, agregue el contenido codificado al final de un archivo de salida.

mopo922
fuente
10
Hay muchos defectos en esta respuesta. Primero, se *.txtdebe citar el comodín (de lo contrario, todo el findcomando, tal como está escrito, es inútil). Otra falla proviene de una idea errónea: el comando que se ejecuta no es cat >> 0.txt {} , pero cat {}. De hecho, su comando es equivalente a { find . -type f -name *.txt -exec cat '{}' \; ; } >> 0.txt(agregué agrupación para que se dé cuenta de lo que realmente está sucediendo). Otra falla es que findva a encontrar el archivo 0.txty catse quejará diciendo que el archivo de entrada es el archivo de salida .
gniourf_gniourf
Gracias por las correcciones. Mi caso era un poco diferente y no había pensado en algunas de esas trampas aplicadas a este caso.
mopo922
Debe poner >> output.fileal final de su comando, para no inducir a nadie (incluido usted) a pensar que findse ejecutará cat {} >> output.filepara cada archivo encontrado.
gniourf_gniourf
¡Comienza a verse realmente bien! Una sugerencia final: use en -exec cat {} +lugar de -exec cat {} \;, de modo que solo una instancia de catse genera con varios argumentos ( +se especifica mediante POSIX ).
gniourf_gniourf
3
Buena respuesta y advertencia: modifiqué la mía a: find . -type f -exec cat {} + >> outputfile.txty no pude entender por qué mi archivo de salida no dejaría de crecer en los conciertos a pesar de que el directorio solo tenía 50 megas. ¡Fue porque seguí agregando outputfile.txt a sí mismo! Así que asegúrese de nombrar ese archivo correctamente o colóquelo en otro directorio por completo para evitar esto.
Thisisstackoverflow
43

si tiene un cierto tipo de salida, haga algo como esto

cat /path/to/files/*.txt >> finalout.txt
Eswar Yaganti
fuente
1
Sin embargo, tenga en cuenta que está perdiendo la posibilidad de mantener el orden de fusión. Esto puede afectarlo si tiene sus archivos nombrados, por ejemplo. file_1, file_2... file_11, debido al orden natural de cómo se ordenan los archivos.
Emix
16

Si todos sus archivos están en un solo directorio, simplemente puede hacer

cat * > 0.txt

Los archivos 1.txt, 2.txt, .. irán a 0.txt

Pooja
fuente
Ya respondido por Eswar. Sin embargo, tenga en cuenta que está perdiendo la posibilidad de mantener el orden de fusión. Esto puede afectarlo si tiene sus archivos nombrados, por ejemplo. file_1, file_2... file_11, debido al orden natural de cómo se ordenan los archivos.
emix
10
for i in {1..3}; do cat "$i.txt" >> 0.txt; done

Encontré esta página porque necesitaba unir 952 archivos en uno solo. Encontré que esto funciona mucho mejor si tienes muchos archivos. Esto hará un bucle para la cantidad de números que necesite y cada uno de ellos usando >> para agregar al final de 0.txt.

Freddythunder
fuente
podría usar la expansión de llaves en bash para escribir cat {1,2,3} .txt >> 0.txt
mcheema
9

Si todos sus archivos tienen un nombre similar, simplemente puede hacer:

cat *.log >> output.log
AIRE
fuente
5

Otra opción es sed:

sed r 1.txt 2.txt 3.txt > merge.txt 

O...

sed h 1.txt 2.txt 3.txt > merge.txt 

O...

sed -n p 1.txt 2.txt 3.txt > merge.txt # -n is mandatory here

O sin redireccionamiento ...

sed wmerge.txt 1.txt 2.txt 3.txt

Tenga en cuenta que la última línea escribe también merge.txt( wmerge.txt¡ no !). Puede usar w"merge.txt"para evitar confusiones con el nombre del archivo y -npara la salida silenciosa.

Por supuesto, también puede acortar la lista de archivos con comodines. Por ejemplo, en el caso de archivos numerados como en los ejemplos anteriores, puede especificar el rango con llaves de esta manera:

sed -n w"merge.txt" {1..3}.txt
Fran
fuente
4

si sus archivos contienen encabezados y desea eliminarlos en el archivo de salida, puede usar:

for f in `ls *.txt`; do sed '2,$!d' $f >> 0.out; done
brunocrt
fuente
3

Si el archivo original contiene caracteres no imprimibles, se perderán al usar el comando cat. Usando 'cat -v', los no imprimibles se convertirán en cadenas de caracteres visibles, pero el archivo de salida aún no contendría los caracteres no imprimibles reales en el archivo original. Con una pequeña cantidad de archivos, una alternativa podría ser abrir el primer archivo en un editor (por ejemplo, vim) que maneja caracteres que no se imprimen. Luego maniobra hasta el final del archivo e ingrese ": r second_file_name". Eso atraerá el segundo archivo, incluidos los caracteres que no se imprimen. Lo mismo podría hacerse para archivos adicionales. Cuando todos los archivos hayan sido leídos, ingrese ": w". El resultado final es que el primer archivo ahora contendrá lo que hizo originalmente, más el contenido de los archivos que se leyeron.

BACooper
fuente
Esto no es muy programable.
FKEinternet
1

Si desea agregar contenido de 3 archivos en un archivo, el siguiente comando será una buena opción:

cat file1 file2 file3 | tee -a file4 > /dev/null

Combinará el contenido de todos los archivos en el archivo 4, arrojando la salida de la consola a /dev/null.

Ajit K'sagar
fuente