Tengo ± 10,000 archivos ( res.1- res.10000) todos consistentes en una columna y un número igual de filas. Lo que quiero es, en esencia, simple; fusionar todos los archivos en columnas en un nuevo archivo final.res. He intentado usar:
paste res.*
Sin embargo (aunque esto parece funcionar para un pequeño subconjunto de archivos de resultados, esto da el siguiente error cuando se realiza en todo el conjunto: Too many open files.
Debe haber una forma 'fácil' de hacer esto, pero desafortunadamente soy bastante nuevo en Unix. ¡Gracias por adelantado!
PD: para darle una idea de cómo se ve (uno de mis) archivos de datos:
0.5
0.5
0.03825
0.5
10211.0457
10227.8469
-5102.5228
0.0742
3.0944
...
command-line
text-processing
columns
paste
esteras
fuente
fuente

--serialopción con elpastecomando?paste --serialno combina archivos en columnas ...paste -shecho funciona, pero pega los archivos de resultados separados en fila en lugar de columna. Sin embargo, esto es algo que puedo resolver. ¡Gracias!Respuestas:
Si tiene permisos de root en esa máquina, puede aumentar temporalmente el límite de "número máximo de descriptores de archivo abiertos":
Y entonces
Después de eso, puede restablecerlo a los valores originales.
Una segunda solución , si no puede cambiar el límite:
Llama
pastea cada archivo una vez, y al final hay un archivo enorme con todas las columnas (toma su minuto).Editar : Uso inútil del gato ... ¡ No !
Como se menciona en los comentarios, el uso de
cathere (cat final.res | paste - $f >temp) no es inútil. La primera vez que se ejecuta el bucle, el archivofinal.resya no existe.pasteentonces fallaría y el archivo nunca se llenará, ni se creará. Con mi solución solocatfalla la primera vezNo such file or directoryypastelee de stdin solo un archivo vacío, pero continúa. El error puede ser ignorado.fuente
ulimit -Snpor límite suave yulimit -Hnpor límite duro-bash: /usr/bin/paste: Argument list too long. Ideas de cómo resolver esto? Perdón por molestarlos.getconf ARG_MAX, solo puede aumentar ese valor al volver a compilar el núcleo. ¿Puedes probar mi segunda solución?catcada vez a través del ciclo, puede comenzar creando unfinal.resarchivo vacío . Probablemente sea una buena idea, en caso de que ya haya unfinal.resarchivo allí.Si la respuesta del caos no es aplicable (porque no tiene los permisos requeridos), puede agrupar las
pastellamadas de la siguiente manera:Esto enumera los archivos 1000 a la vez en archivos llamados
lists00,lists01etc., luego pega losres.archivos correspondientes en archivos con nombremerge00,merge01etc., y finalmente combina todos los archivos parcialmente fusionados resultantes.Como lo menciona el caos , puede aumentar la cantidad de archivos utilizados a la vez; el límite es el valor dado
ulimit -nmenos la cantidad de archivos que ya tiene abiertos, por lo que diríausar el límite menos diez.
Si su versión de
splitno es compatible-d, puede eliminarla: todo lo que hace es indicarlesplitque use sufijos numéricos. Por defecto, los sufijos seránaa,abetc. en lugar de01,02etc.Si hay tantos archivos que
ls -1 res.*fallan ("lista de argumentos demasiado larga"), puede reemplazarla confindque evitará ese error:(Como lo señaló don_crissti ,
-1no debería ser necesario al canalizarlsla salida; pero lo dejo para manejar los casos en los quelstiene un alias-C).fuente
Intenta ejecutarlo de esta manera:
También puede dividir el lote en partes y probar algo como:
y al final combinar archivos finales
fuente
Too many open filesfinal.x00canalizaciones, ya sea como denominadas FIFO, o implícitamente, utilizando la sustitución del proceso (si su shell lo admite, por ejemplo, bash). No es divertido escribirlo a mano, pero puede adaptarse a un archivo MAKE.No creo que esto sea tan complicado como todo eso: ya has hecho el trabajo duro ordenando los nombres de archivo. Simplemente no los abras a todos al mismo tiempo, eso es todo.
De otra manera:
... pero creo que eso los hace al revés ... Esto podría funcionar mejor:
Y aquí hay otra forma:
Eso permite
tarreunir todos los archivos en una secuencia delimitada por nulos, analiza todos sus metadatos de encabezado pero el nombre de archivo y transforma todas las líneas en todos los archivos en pestañas. Sin embargo, se basa en que la entrada es archivos de texto reales, lo que significa que cada uno termina con una nueva línea y no hay bytes nulos en los archivos. Ah, y también depende de que los nombres de los archivos estén libres de nueva línea (aunque eso podría manejarse de manera sólida contarla--xformopción de GNU ) . Dado que se cumplen estas condiciones, debería hacer un trabajo muy corto de cualquier número de archivos, ytarlo hará casi todo.El resultado es un conjunto de líneas que se ven así:
Y así.
Lo probé creando primero 5 archivos de prueba. Realmente no tenía ganas de generar archivos 10000 en este momento, así que solo fui un poco más grande para cada uno, y también me aseguré de que las longitudes de los archivos diferían en gran medida. Esto es importante cuando se prueban
tarscripts porquetarbloqueará la entrada a longitudes fijas; si no prueba al menos algunas longitudes diferentes, nunca sabrá si realmente manejará solo una.De todos modos, para los archivos de prueba que hice:
lsluego informó:... entonces corrí ...
... solo para mostrar solo los primeros 25 campos delimitados por tabulaciones por línea (porque cada archivo es una sola línea, hay muchos ) ...
El resultado fue:
fuente
Dada la cantidad de archivos, tamaños de línea, etc. involucrados, creo que superará los tamaños predeterminados de las herramientas (awk, sed, paste, *, etc.)
Crearía un pequeño programa para esto, no tendría 10,000 archivos abiertos, ni una línea de cientos de miles de longitud (10,000 archivos de 10 (tamaño máximo de línea en el ejemplo)). Solo requiere una matriz de enteros de ~ 10,000, para almacenar el número de bytes que se han leído de cada archivo. La desventaja es que solo tiene un descriptor de archivo, se reutiliza para cada archivo, para cada línea, y esto podría ser lento.
Las definiciones de
FILESyROWSdeben cambiarse a los valores exactos reales. La salida se envía a la salida estándar.fuente