Premisa
No debe incurrir en ese error solo para 15k archivos con ese formato de nombre específico [ 1 , 2 ] .
Si está ejecutando esa expansión desde otro directorio y tiene que agregar la ruta a cada archivo, el tamaño de su comando será mayor y, por supuesto, puede ocurrir.
La solución ejecuta el comando desde ese directorio.
(cd That/Directory ; cat file_{1..2000}.pdb >> file_all.pdb )
La mejor solución Si en cambio adiviné mal y lo ejecutas desde el directorio en el que están los archivos ... En
mi humilde opinión, la mejor solución es la de Stéphane Chazelas :
seq -f 'file_%.17g.pdb' 15000 | xargs cat > file_all.pdb
con printf o seq; probado en archivos de 15k con solo su número dentro de la memoria caché previa, es incluso el más rápido (en la actualidad, excepto el OP del mismo directorio en el que se encuentran los archivos).
Algunas palabras mas
Debería poder pasar a sus líneas de comando de shell más tiempo.
Su línea de comando tiene 213914 caracteres y contiene 15003 palabras.
cat file_{1..15000}.pdb " > file_all.pdb" | wc
... incluso agregar 8 bytes para cada palabra es 333 938 bytes (0.3M) muy por debajo del 2097142 (2.1M) reportado ARG_MAX
en un kernel 3.13.0 o el 2088232 ligeramente más pequeño reportado como "Longitud máxima de comando que podríamos realmente utilizar " porxargs --show-limits
Eche un vistazo en su sistema a la salida de
getconf ARG_MAX
xargs --show-limits
Solución guiada de la pereza
En casos como este, prefiero trabajar con bloques, incluso porque generalmente sale una solución eficiente en el tiempo.
La lógica (si la hay) es que soy demasiado vago para escribir 1 ... 1000 1001..2000, etc., etc.
Así que le pido a un script que lo haga por mí.
Solo después de comprobar que la salida es correcta, la redirijo a un script.
... pero la pereza es un estado mental .
Como soy alérgico a xargs
(realmente debería haberlo usado xargs
aquí) y no quiero comprobar cómo usarlo, termino puntualmente para reinventar la rueda como en los ejemplos a continuación (tl; dr).
Tenga en cuenta que, dado que los nombres de los archivos están controlados (sin espacios, líneas nuevas ...), puede seguir fácilmente algo como el script a continuación.
tl; dr
Versión 1: pase como parámetro opcional el primer número de archivo, el último, el tamaño del bloque, el archivo de salida
#!/bin/bash
StartN=${1:-1} # First file number
EndN=${2:-15000} # Last file number
BlockN=${3:-100} # files in a Block
OutFile=${4:-"all.pdb"} # Output file name
CurrentStart=$StartN
for i in $(seq $StartN $BlockN $EndN)
do
CurrentEnd=$i ;
cat $(seq -f file_%.17g.pdb $CurrentStart $CurrentEnd) >> $OutFile;
CurrentStart=$(( CurrentEnd + 1 ))
done
# Here you may need to do a last iteration for the part cut from seq
[[ $EndN -ge $CurrentStart ]] &&
cat $(seq -f file_%.17g.pdb $CurrentStart $EndN) >> $OutFile;
Versión 2
Llamando a bash para la expansión (un poco más lento en mis pruebas ~ 20%).
#!/bin/bash
StartN=${1:-1} # First file number
EndN=${2:-15000} # Last file number
BlockN=${3:-100} # files in a Block
OutFile=${4:-"all.pdb"} # Output file name
CurrentStart=$StartN
for i in $(seq $StartN $BlockN $EndN)
do
CurrentEnd=$i ;
echo cat file_{$CurrentStart..$CurrentEnd}.pdb | /bin/bash >> $OutFile;
CurrentStart=$(( CurrentEnd + 1 ))
done
# Here you may need to do a last iteration for the part cut from seq
[[ $EndN -ge $CurrentStart ]] &&
echo cat file_{$CurrentStart..$EndN}.pdb | /bin/bash >> $OutFile;
Por supuesto, puede avanzar y deshacerse por completo de seq
[ 3 ] (de coreutils) y trabajar directamente con las variables en bash, o usar python, o compilar un programa de CA para hacerlo [ 4 ] ...