Muchos archivos de texto en un archivo de texto grande

Muchos archivos de texto en un archivo de texto grande

Quiero combinar miles de pequeños archivos de texto en un archivo de texto grande. Los tengo en directorios con la estructura: timestamp1/status.txt. Por ejemplo: 20130430133144/status.txt. Hasta ahora sé que

cat */* > bigtextfile.txt

Funciona para pequeñas cantidades de archivos. ¿Pero funcionará para números más altos? Me pregunto si catrecopilaremos el contenido de todos los archivos y luego intentaremos guardarlos en el archivo bigtextfile. De lo contrario, supongo que debe haber otra forma de hacerlo, como buscar un archivo, agregarlo bigtextfile, luego buscar otro y así sucesivamente.

Respuesta1

En:

cat */* > bigtextfile.txt

El shell se expandirá */*a la lista ordenada de archivos coincidentes (no ocultos) y se ejecutará catcon esas rutas de archivo como argumentos.

catAbrirá cada archivo por turno y escribirá en su salida estándar lo que lee del archivo. catno contendrá más de un búfer lleno de datos (algo así como unos pocos kilobytes) a la vez en la memoria.

Sin embargo, un problema que puede encontrar es que la lista de argumentos cates tan grande que alcanza el límite del tamaño de argumentos de la execve()llamada al sistema. Por lo tanto, es posible que deba dividir esa lista de archivos y ejecutarla catvarias veces.

Podrías usar xargspara eso (aquí con GNU o BSD para las opciones xargsno estándar ):-r-0

printf '%s\0' */* | xargs -r0 cat -- > big-file.txt

(debido a que printfestá integrado en el shell, no pasa por la execvellamada al sistema, por lo que no pasa por su límite).

O findhaga la lista de archivos y ejecute tantos comandos cat como sea necesario:

find . -mindepth 2 -maxdepth 2 -type f -exec cat {} + > big-file.txt

O portátil:

find . -path './*/*' -prune -type f -exec cat {} + > big-file.txt

(Sin embargo, tenga en cuenta que, al contrario de */*, incluirá archivos ocultos (y archivos en directorios ocultos), no buscará archivos en enlaces simbólicos a directorios y la lista de archivos no se ordenará).

Si tiene una versión reciente de Linux, puede eliminar el límite del tamaño de los argumentos haciendo:

ulimit -s unlimited
cat -- */* > big-file.txt

Con zsh, también puedes usar zargs:

autoload zargs
zargs -- */* -- cat > big-file.txt

Con ksh93, puedes usar command -x:

command -x cat -- */* > big-file.txt

Todos hacen lo mismo, dividen la lista de archivos y ejecutan tantos catcomandos como sean necesarios.

Nuevamente ksh93, puedes superar el execve()límite usando el catcomando incorporado:

command /opt/ast/bin/cat -- */* > big-file.txt

Respuesta2

No, catno almacenará en búfer todos los archivos antes de que comience a escribirse.

Sin embargo, si tiene una gran cantidad de archivos, puede tener un problema con la cantidad de argumentos pasados cat. De forma predeterminada, el kernel de Linux solo permite pasar una cantidad fija de argumentos a cualquier programa (no recuerdo cómo obtener el valor, pero en la mayoría de los casos son unos pocos miles).
Para resolver este problema, puedes hacer algo como esto:

find -mindepth 2 -maxdepth 2 -type f -exec cat {} \; > bigtextfile.txt

Básicamente, esto llamará catpor separado a todos y cada uno de los archivos encontrados por find.

Respuesta3

Si la cantidad de archivos es demasiado grande, se */*obtendrá una lista de argumentos demasiado grande. Si es así, algo parecido servirá:

find . -name "*.txt" | xargs cat > outfile

(La idea es utilizar findpara recoger los nombres de los archivos y convertirlos en una secuencia; xargscorta esta secuencia en partes manejables para entregárselas cat, lo que las concatena en la secuencia de salida de xargsy que va a outfile).

información relacionada