Eu recebo o seguinte erro ao tentar ls *.txt | wc -l
um diretório que contém muitos arquivos:
-bash: /bin/ls: Argument list too long
O limite dessa "lista de argumentos" depende da distribuição ou das especificações do computador? Normalmente, eu canalizaria o resultado de um resultado tão grande para outros comandos ( wc -l
por exemplo), então não estou preocupado com os limites do terminal.
ls
de saída , que é uma má idéia, então é melhor evitá-lo. Para contar, consulte Qual é a melhor maneira de contar o número de arquivos em um diretório? , para uma solução alternativa complicada, veja por que o loop for não gera o erro "argumento muito longo"? .Respostas:
A lista de argumentos da mensagem de erro muito longa vem do * de
ls *.txt
.Este limite é uma segurança para os programas binários e para o seu Kernel. Você verá nesta página mais informações sobre ele e como ele é usado e calculado.
Não existe esse limite no tamanho do tubo. Então você pode simplesmente emitir este comando:
Nota: No Linux moderno, caracteres estranhos em nomes de arquivos (como novas linhas) serão escapados com ferramentas como
ls
oufind
, mas ainda serão exibidos em * . Se você estiver em um Unix antigo, precisará deste comandoNB2: Eu queria saber como é possível criar um arquivo com uma nova linha em seu nome. Não é tão difícil assim que você conhece o truque:
fonte
-maxdepth 1
se não pretender contar arquivos em subdiretórios.-exec echo \;
.find
. Nofind
OS X e em sistemas baseados em busybox, e eu acho que qualquer sistema baseado em BSD mostra o nome do arquivo com uma nova linha, o que atrapalha a contagem.wc -l
está contando novas linhas. Então, queremos que ele tenha novas linhas.Depende principalmente da sua versão do kernel do Linux.
Você poderá ver o limite do seu sistema executando
que informa o número máximo de bytes que uma linha de comando pode ter após ser expandida pelo shell.
No Linux <2.6.23, o limite geralmente é de 128 KB.
No Linux> = 2.6.25, o limite é de 128 KB ou 1/4 do tamanho da pilha (consulte
ulimit -s
), o que for maior.Veja a página de manual execve (2) para todos os detalhes.
Infelizmente, a tubulação
ls *.txt
não vai resolver o problema, porque o limite está no sistema operacional, não no shell.O shell expande o
*.txt
e tenta chamare você tem tantos arquivos correspondentes
*.txt
que está excedendo o limite de 128 KB.Você terá que fazer algo como
em vez de.
(E veja os comentários de Shawn J. Goff abaixo sobre nomes de arquivos que contêm novas linhas.)
fonte
.
e o que-maxdepth 1
significa na última linha? Obrigado! : D.
significa diretório atual,-maxdepth 1
significa que não aparece em subdiretórios. O objetivo era combinar os mesmos arquivos que*.txt
.Outra solução alternativa:
Mesmo que
ls
produza mais saída do quels *.txt
produz (ou tente produzir), ele não se depara com o problema "argumento muito longo", porque você não está passando nenhum argumento parals
. Observe quegrep
usa uma expressão regular em vez de um padrão de correspondência de arquivo.Você pode querer usar:
(supondo que sua versão do
ls
suporte esta opção). Isso dizls
para não classificar sua saída, o que poderia economizar tempo e memória - e, nesse caso, a ordem não importa, já que você está apenas contando arquivos. Os recursos gastos na classificação da saída geralmente não são significativos, mas nesse caso já sabemos que você tem um número muito grande de*.txt
arquivos.E você deve reorganizar seus arquivos para não ter tantos em um único diretório. Isso pode ou não ser viável.
fonte
MAX_ARG_PAGES parece ser um parâmetro do kernel. Usar
find
exargs
é uma combinação típica para abordar esse limite, mas não tenho certeza de que funcionewc
.Canalizar a saída de
find . -name \*\.txt
um arquivo e contar as linhas nesse arquivo deve servir como uma solução alternativa.fonte
ls
a saída de, não vai resolver isso. Desde que o curinga * .txt seja expandido acima do limite, falhará antes mesmo de iniciarls
e gerar qualquer saída.ls
lo, você deve especificar-maxdepth 1
para evitar a varredura recursiva dos subdiretórios.Isso pode estar sujo, mas funciona para as minhas necessidades e dentro da minha competência. Eu não acho que ele tenha um desempenho muito rápido, mas me permitiu continuar meu dia.
Eu estava recebendo uma lista longa de 90.000 jpgs e os canalizava para avconv para gerar um intervalo de tempo.
Eu estava usando ls * .jpg | avconv antes de me deparar com esta questão.
fonte