Premissa
Você não deve incorrer nesse erro em apenas 15k arquivos com esse formato de nome específico [ 1 , 2 ] .
Se você estiver executando essa expansão em outro diretório e precisar adicionar o caminho a cada arquivo, o tamanho do seu comando será maior e, é claro, pode ocorrer.
Solução execute o comando desse diretório.
(cd That/Directory ; cat file_{1..2000}.pdb >> file_all.pdb )
Melhor solução Se, em vez disso, eu adivinhei mal e você o executou no diretório em que os arquivos estão ...
IMHO, a melhor solução é a de Stéphane Chazelas :
seq -f 'file_%.17g.pdb' 15000 | xargs cat > file_all.pdb
com printf ou seq; testado em arquivos de 15k com apenas seu número pré-armazenado em cache, é ainda o mais rápido (atualmente e exceto o OP do mesmo diretório em que os arquivos estão).
Algumas palavras mais
Você deve poder passar para as linhas de comando do shell por mais tempo.
Sua linha de comando tem 213914 caracteres e contém 15003 palavras
cat file_{1..15000}.pdb " > file_all.pdb" | wc
... mesmo adicionar 8 bytes para cada palavra é 333 938 bytes (0,3M) muito abaixo dos 2097142 (2,1M) relatados ARG_MAX
no kernel 3.13.0 ou do 2088232 um pouco menor relatado como "Comprimento máximo de comando que poderíamos realmente use " porxargs --show-limits
Dê uma olhada no seu sistema para obter a saída de
getconf ARG_MAX
xargs --show-limits
Solução guiada por preguiça
Em casos como esse, prefiro trabalhar com blocos, mesmo porque geralmente são uma solução eficiente em termos de tempo.
A lógica (se houver) é que estou com preguiça de escrever 1 ... 1000 1001..2000 etc etc ...
Então, peço a um script que faça isso por mim.
Somente depois de verificar a saída, a correção é redirecionada para um script.
... mas a preguiça é um estado de espírito .
Como sou alérgico a xargs
(eu realmente deveria ter usado xargs
aqui) e não quero verificar como usá-lo, termino pontualmente para reinventar a roda, como nos exemplos abaixo (tl; dr).
Observe que, como os nomes dos arquivos são controlados (sem espaços, novas linhas ...), você pode usar facilmente algo como o script abaixo.
tl; dr
Versão 1: passe como parâmetro opcional o 1º número do arquivo, o último, o tamanho do bloco, o arquivo de saída
#!/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;
Versão 2
Chamando bash para a expansão (um pouco mais lento nos meus testes ~ 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;
Claro que você pode seguir em frente e se livrar completamente de seq
[ 3 ] (do coreutils) e trabalhar diretamente com as variáveis no bash, usar python ou compilar um programa ac para fazê-lo [ 4 ] ...