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
--serial
opción con elpaste
comando?paste --serial
no combina archivos en columnas ...paste -s
hecho 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
paste
a 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
cat
here (cat final.res | paste - $f >temp
) no es inútil. La primera vez que se ejecuta el bucle, el archivofinal.res
ya no existe.paste
entonces fallaría y el archivo nunca se llenará, ni se creará. Con mi solución solocat
falla la primera vezNo such file or directory
ypaste
lee de stdin solo un archivo vacío, pero continúa. El error puede ser ignorado.fuente
ulimit -Sn
por límite suave yulimit -Hn
por 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?cat
cada vez a través del ciclo, puede comenzar creando unfinal.res
archivo vacío . Probablemente sea una buena idea, en caso de que ya haya unfinal.res
archivo allí.Si la respuesta del caos no es aplicable (porque no tiene los permisos requeridos), puede agrupar las
paste
llamadas de la siguiente manera:Esto enumera los archivos 1000 a la vez en archivos llamados
lists00
,lists01
etc., luego pega losres.
archivos correspondientes en archivos con nombremerge00
,merge01
etc., 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 -n
menos la cantidad de archivos que ya tiene abiertos, por lo que diríausar el límite menos diez.
Si su versión de
split
no es compatible-d
, puede eliminarla: todo lo que hace es indicarlesplit
que use sufijos numéricos. Por defecto, los sufijos seránaa
,ab
etc. en lugar de01
,02
etc.Si hay tantos archivos que
ls -1 res.*
fallan ("lista de argumentos demasiado larga"), puede reemplazarla confind
que evitará ese error:(Como lo señaló don_crissti ,
-1
no debería ser necesario al canalizarls
la salida; pero lo dejo para manejar los casos en los quels
tiene 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 files
final.x00
canalizaciones, 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
tar
reunir 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 contar
la--xform
opción de GNU ) . Dado que se cumplen estas condiciones, debería hacer un trabajo muy corto de cualquier número de archivos, ytar
lo 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
tar
scripts porquetar
bloqueará 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:
ls
luego 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
FILES
yROWS
deben cambiarse a los valores exactos reales. La salida se envía a la salida estándar.fuente