¿Cómo fusionar todos los archivos (de texto) en un directorio en uno?

89

Tengo 14 archivos que forman parte de un solo texto. Me gustaría fusionarlos en uno. ¿Como hacer eso?

Ivan
fuente

Respuestas:

168

Esto es técnicamente lo que catse supone que debe hacer ("concatenate"), a pesar de que la mayoría de las personas simplemente lo usan para generar archivos en stdout. Si le da varios nombres de archivo, los generará todos secuencialmente y luego podrá redirigirlos a un nuevo archivo; en el caso de todos los archivos, simplemente use *(o /path/to/directory/*si aún no está en el directorio) y su shell lo expandirá a todos los nombres de archivo

$ cat * > merged-file
Michael Mrozek
fuente
15
Tenga en cuenta que su comando entre comillas probablemente solo hará lo que el póster quiere si están numerados de tal manera que el shell se expanda *en orden "natural". Si tiene "file1.txt ... file9.txt ... file14.txt" no funcionará porque file1? .Txt se ordenará entre file1.txt y file2.txt. Debería cambiarles el nombre a "file01.txt ... file09.txt ... file14.txt". Di echo *si no estás seguro.
Warren Young el
2
@Warren: buen punto (o puede usar zsh y configurar su numeric_glob_sortopción).
Gilles
2
@ warren-young un comentario de advertencia correcto y útil. Pero en mi caso real, el orden no hace ninguna diferencia (porque los archivos contienen simples sentencias SQL que insertan registros de datos que no tienen dependencias).
Ivan
2
Tenga cuidado, si el recuento de archivos excede un cierto límite, puede ejecutar errores como - / bin / cat: Lista de argumentos demasiado larga
Nupur
1
@ ARA1307 Solo si el archivo ya existe; de lo contrario, el globo se expandirá antes de que el shell abra el archivo para escribir en él. Buen punto en esa situación sin embargo
Michael Mrozek
25

Si sus archivos no están en el mismo directorio, puede usar el comando find antes de la concatenación:

find /path/to/directory/ -name *.csv -print0 | xargs -0 -I file cat file > merged.file

Muy útil cuando sus archivos ya están ordenados y desea fusionarlos para analizarlos.


Más portátil:

find /path/to/directory/ -name *.csv -exec cat {} + > merged.file

Esto puede o no preservar el orden de los archivos.

3nrique0
fuente
1
Este es el camino a seguir si tiene muchos archivos. Evita un error de "lista de argumentos demasiado larga".
Мати Тернер
2
Necesita -name "* .csv" en lugar de -name * .csv; sin las comillas, falla.
Peteris
La necesidad de comillas depende de la versión del comando find, especialmente en find and awk, es un problema cuando estás en una Mac, las versiones de ambos programas son un poco viejas. Hasta ahora en ubuntu, fedora, debian y CentOS, funcionó sin problemas sin las comillas
3nrique0
Esperaría que la versión sin comillas funcione cuando no hay archivos en el directorio actual que coincidan con el patrón "*.csv", ya que el shell pasaría el literal *a find.
RJHunter
9

El comando

$ cat * > merged-file

en realidad tiene el efecto secundario no deseado de incluir 'archivo combinado' en la concatenación, creando un archivo fuera de control. Para evitar esto, escriba el archivo combinado en un directorio diferente;

$ cat * > ../merged-file

o use una coincidencia de patrón que ignorará el archivo combinado;

$ cat *.txt > merged-file
Christopher Jones
fuente
14
cat * > merged-filefunciona bien. Los globos se procesan antes de crear el archivo. Si merged-fileya existe, cat(al menos el mío) detectará que es el archivo de salida y se negará a leerlo. SI el archivo ya existe Y tiene la redirección más adelante en la tubería, entonces obviamente no puede hacer eso, así que solo entonces obtendrá el archivo fuera de control.
Kevin
catno tiene forma de detectar si el archivo es el de salida. La redirección ocurre en el shell; catsolo imprime en stdout.
bfontaine
8

Como dicen los otros de aquí ... Puedes usar cat

Digamos que tienes:

~/file01
~/file02
~/file03
~/file04
~/fileA
~/fileB
~/fileC
~/fileD

Y desea que sólo file01a file03y fileAa fileC:

cat ~/file01 ~/file02 ~/file03 ~/fileA ~/fileB ~/fileC > merged-file

O, usando la expansión de llaves:

cat ~/file0{1..3} ~/file{A..C} > merged-file

O, utilizando una expansión de llave más elegante:

cat ~/file{0{1..3},{A..C}} > merged-file

O puedes usar forloop:

for i in file0{1..3} file{A..C}; do cat ~/"$i"; done > merged-file
Florin Idita
fuente
1
Tenga en cuenta que la cadena [01-03]no funcionará como un patrón global.
Kusalananda
0

Puede especificar el patternde un archivo y luego combinarlos todos de la siguiente manera:

cat *pattern* >> mergedfile
usuario182845
fuente
0

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 de escritura también merge.txt (no wmerge.txt!). Puede usar w "merge.txt" para evitar confusiones con el nombre del archivo y -n para 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
Harini
fuente