variable concatenate and unix concatenation cat

unix - concatenate - ¿Cuál es la forma más rápida de catar múltiples archivos?



cat options (8)

Me pregunto si hay una manera de concatenar archivos de texto Unix juntos más rápido que ejecutar cat .

Aquí está el problema que estoy enfrentando. Estoy procesando un archivo de texto de tamaño ~ 100G. Estoy intentando mejorar el tiempo de ejecución dividiendo el archivo en cientos de archivos más pequeños y procesándolos en paralelo. Al final, los archivos resultantes vuelven a estar juntos en orden. El tiempo de lectura / escritura del archivo en sí mismo toma horas. Me gustaría encontrar una manera de mejorar lo siguiente:

cat file1 file2 file3 ... fileN >> newBigFile

  1. Esto requiere el doble de espacio en el disco ya que fileN ... fileN ocupa 100G, y luego newBigFile toma otros 100Gb, y luego fileN ... fileN se elimina

  2. Los datos ya están en el fileN ... fileN , haciendo el cat >> incurre en tiempo de lectura y escritura cuando todo lo que realmente necesito es que los cientos de archivos vuelvan a aparecer como 1 archivo ...


¿Es posible que usted simplemente no divida el archivo? En su lugar, procese el archivo en trozos configurando el puntero del archivo en cada uno de sus trabajadores paralelos. Si el archivo necesita ser procesado en una línea orientada, eso lo hace más complicado pero aún puede hacerse. Cada trabajador debe comprender que, en lugar de comenzar con el desplazamiento que le da, primero debe buscar byte a byte en la próxima nueva línea +1. Cada trabajador también debe comprender que no procesa la cantidad establecida de bytes que le da, sino que debe procesar la primera línea nueva después de la cantidad establecida de bytes que se asigna para procesar.

La asignación y configuración reales del puntero del archivo es bastante sencilla. Si hay n trabajadores, cada uno procesa n / bytes de tamaño de archivo y el puntero del archivo comienza en el número de trabajador * n / file_size.

¿Hay alguna razón por la que ese tipo de plan no sea suficiente?


¿Solución rápida, pero no gratuita? Obtenga una unidad SSD o un almacenamiento basado en PCIe flash. Si esto es algo que se debe hacer de forma regular, aumentar la velocidad de la E / S del disco será la más rentable y la velocidad más rápida que puede obtener.


Creo que esta es la forma más rápida de controlar todos los archivos contenidos en la misma carpeta:

$ ls [path to folder] | while read p; do cat $p; done


Cuando concatene archivos nuevamente, puede eliminar los archivos pequeños a medida que se agregan:

for file in file1 file2 file3 ... fileN; do cat "$file" >> bigFile && rm "$file" done

Esto evitaría la necesidad de duplicar el espacio.

No hay otra forma de hacer mágicamente archivos concatenados mágicamente. La API del sistema de archivos simplemente no tiene una función que lo haga.


Hay tal cosa como demasiada concurrencia.

Una mejor manera de hacer esto sería utilizar lecturas de acceso aleatorio en el archivo a lo largo de los rangos deseados y nunca dividirlo y procesar solo el número de archivos como el número de CPU / Cores físicos en la máquina. Eso es, a menos que también esté saturando el disco con IOPS, entonces debería reducirlo hasta que el disco no sea el cuello de botella.

Lo que está haciendo de cualquier manera con toda la ingenua división / copia / eliminación es generar toneladas de IOPS y no hay forma de evitarlo.

Una solución transparente que probablemente requiera más trabajo del que vale la pena, a menos que se trate de un problema / problema diario en curso, es escribir un sistema de archivos FUSE personalizado que represente a un solo archivo como archivos múltiples. Hay muchos ejemplos sobre cómo tratar el contenido de los archivos de archivo como archivos individuales que le mostrarán los conceptos básicos de cómo hacerlo.


Si no necesita acceso aleatorio al archivo grande final (es decir, simplemente lo leyó una vez de principio a fin), puede hacer que sus cientos de archivos intermedios aparezcan como uno solo. Donde normalmente haria

$ consume big-file.txt

en lugar de hacer

$ consume <(cat file1 file2 ... fileN)

Esto utiliza la sustitución del proceso de Unix, a veces también llamada "canalizaciones anónimas con nombre".

También puede ahorrar tiempo y espacio al dividir su entrada y al mismo tiempo hacer el procesamiento; GNU Parallel tiene un --pipe switch que hará precisamente esto. También puede volver a ensamblar las salidas de nuevo en un archivo grande, potencialmente usando menos espacio para rascar, ya que solo necesita mantener el número de núcleos en el disco a la vez. Si está ejecutando literalmente sus cientos de procesos al mismo tiempo, Parallel mejorará en gran medida su eficiencia al permitirle ajustar la cantidad de paralelismo a su máquina. Lo recomiendo altamente.


Tal vez dd sería más rápido porque no tendrías que pasar cosas entre cat y shell. Algo como:

mv file1 newBigFile dd if=file2 of=newBigFile seek=$(stat -c %s newBigFile)


todo lo que realmente necesito es que los cientos de archivos vuelvan a aparecer como 1 archivo ...

La razón por la que no es práctico simplemente unir archivos de esta manera a nivel de sistema de archivos, ya que los archivos de texto no suelen llenar un bloque de disco exactamente, por lo que los datos en los archivos subsiguientes deberían ser movidos hacia arriba para llenar los vacíos, causando Un montón de lecturas / escrituras de todos modos .