Concatenando múltiples archivos de texto en un solo archivo en Bash

305

¿Cuál es la forma más rápida y pragmática de combinar todos los archivos * .txt en un directorio en un archivo de texto grande?

Actualmente estoy usando Windows con Cygwin, así que tengo acceso a BASH.

El comando de shell de Windows también sería bueno, pero dudo que haya uno.

Yada
fuente

Respuestas:

537

Esto agrega la salida a all.txt

cat *.txt >> all.txt

Esto sobrescribe all.txt

cat *.txt > all.txt
Robert Greiner
fuente
30
puede encontrarse con un problema en el que cat all.txt en all.txt ... A veces tengo este problema con grep, no estoy seguro si cat tiene el mismo comportamiento.
rmeador
8
@rmeador sí, eso es cierto, si all.txt ya existe tendrás este problema. Este problema se resuelve proporcionando el archivo de salida con una extensión diferente o moviendo all.txt a una carpeta diferente.
Robert Greiner
2
cat * .txt >> tmp; mv tmp all.txt (y asegúrese de que all.txt no exista previamente)
Renaud
16
Me aparece "Lista de argumentos demasiado larga". Supongo que no puede manejar más de 40,000 archivos.
Matt
32
Evite la lista de argumentos demasiado tiempo con:echo *.txt | xargs cat > all.txt
5heikki
145

Solo recuerde, para todas las soluciones dadas hasta ahora, el shell decide el orden en que se concatenan los archivos. Para Bash, IIRC, ese es el orden alfabético. Si el orden es importante, debe nombrar los archivos adecuadamente (01file.txt, 02file.txt, etc.) o especificar cada archivo en el orden en que desea concatenarlo.

$ cat file1 file2 file3 file4 file5 file6 > out.txt
Chinmay Kanchi
fuente
33

El comando de shell de Windows typepuede hacer esto:

type *.txt >outputfile

El typecomando Tipo también escribe nombres de archivo en stderr, que no son capturados por el >operador de redireccionamiento (pero aparecerán en la consola).

Greg Hewgill
fuente
2
Solo tenga en cuenta que si coloca el archivo de salida en el mismo directorio que el archivo original, causará una duplicación porque también combinará el nuevo archivo de salida dos veces.
CathalMF
26

Puede usar el shell de Windows copypara concatenar archivos.

C:\> copy *.txt outputfile

De la ayuda:

Para agregar archivos, especifique un solo archivo para el destino, pero varios archivos para el origen (utilizando comodines o formato de archivo1 + archivo2 + archivo3).

Carl Norum
fuente
Esto, como la solución más limpia de IMHO, básicamente sin efectos secundarios que los principiantes puedan tropezar desafortunadamente no se aprecia lo suficiente :-(
Grmpfhmbl
OP pidió Bash.
Big Rich
2
¿Leíste la pregunta? "El comando de shell de Windows también sería bueno ..."
Carl Norum
8

Tenga cuidado, porque ninguno de estos métodos funciona con una gran cantidad de archivos. Personalmente, usé esta línea:

for i in $(ls | grep ".txt");do cat $i >> output.txt;done

EDITAR: como alguien dijo en los comentarios, puede reemplazar $(ls | grep ".txt")con$(ls *.txt)

EDITAR: gracias a la experiencia de @gnourf_gnourf, el uso de glob es la forma correcta de iterar sobre los archivos en un directorio. En consecuencia, las expresiones blasfemas como $(ls | grep ".txt")deben ser reemplazadas por *.txt(ver el artículo aquí ).

Buena solución

for i in *.txt;do cat $i >> output.txt;done
Jacobe2169
fuente
1
¿Por qué no for i in $(ls *.txt);do cat $i >> output.txt;done?
streamofstars
2
Enlace obligatorio ParsingLs , junto con un voto negativo (y usted merece más de un voto ls | grepnegativo , porque es un antipatrón muy malo).
gniourf_gniourf
Recibí un voto positivo porque permite realizar pruebas / operaciones arbitrarias por nombre de archivo antes de la salida y es rápido, fácil y bueno para la práctica. (En mi caso, quería: para i in *; do echo -e "\ n $ i: \ n"; cat $ 1; hecho)
Nathan Chappell
¿No ls *.txtfallaría si hay demasiados archivos (la lista de argumentos es demasiado larga)?
Rafael Almeida
6

La forma más pragmática con el shell es el comando cat. otras formas incluyen,

awk '1' *.txt > all.txt
perl -ne 'print;' *.txt > all.txt
ghostdog74
fuente
1
Esta debería ser la respuesta correcta para la mayoría de las circunstancias. Si hay algún archivo de texto sin una nueva línea vacía, el uso de todo el catmétodo anterior concatenará la última línea y la primera línea de los archivos adyacentes.
mootmoot
6

¿Qué tal este enfoque?

find . -type f -name '*.txt' -exec cat {} + >> output.txt
GPrathap
fuente
Dado que OP dice que los archivos están en el mismo directorio, es posible que deba agregar -maxdepth 1al findcomando.
codeforester
1
Funciona muy bien con una gran cantidad de archivos, donde el enfoque de la respuesta aceptada falla
amine
ah desearía saber qué significa esto más y doble redirección significan ...
hello_earth
Esta debería ser la respuesta correcta. Funcionará correctamente en un script de shell. Aquí hay un método similar si desea ordenar la salida:sort -u --output="$OUTPUT_FILE" --files0-from=- < <(find "$DIRECTORY_NAME" -maxdepth 1 -type f -name '*.txt' -print0)
steveH
3
type [source folder]\*.[File extension] > [destination folder]\[file name].[File extension]

Por ejemplo:

type C:\*.txt > C:\1\all.txt

Eso tomará todos los archivos txt en la carpeta C: \ y lo guardará en la carpeta C: \ 1 con el nombre de all.txt

O

type [source folder]\* > [destination folder]\[file name].[File extension]

Por ejemplo:

type C:\* > C:\1\all.txt

Eso tomará todos los archivos que están presentes en la carpeta y colocará Contenido en C: \ 1 \ all.txt

O yo
fuente
0

Puedes hacer así: cat [directory_path]/**/*.[h,m] > test.txt

Si {}suele incluir la extensión de los archivos que desea buscar, hay un problema de secuencia.

Michael-zhang
fuente
0

Cuando se encuentra con un problema en el que se conecta all.txt a all.txt, puede intentar verificar si all.txt existe o no, si existe, elimine

Me gusta esto:

[ -e $"all.txt" ] && rm $"all.txt"

León
fuente
cat *.txt > all.txt >el comando sobrescribe all.txt si existe >>agrega datos al archivo existente
Oleg Bondarenko
-4

todo eso es desagradable ...

ls | grep *.txt | while read file; do cat $file >> ./output.txt; done;

cosas fáciles

kSiR
fuente
66
Eeek! No hagas eso. Hacerfind . -iname "*.txt" -maxdepth 1 -exec cat {} >> out.txt \;
Chinmay Kanchi