Shell: Erro: Argument list too long

Palavras-chave: shell, Argument list too long, /bin/rm, /bin/mv, bash, ksh, sh

Sistemas operacionais UNIX normalmente têm um tamanho fixo de memória que pode ser utilizada para variáveis de ambiente e argumentos na chamada de um programa. Este tamanho varia de sistema operacional para sistema operacional. Para obter este valor pode-se executar o seguinte comando:

$ getconf ARG_MAX
131072

Quando executamos algum comando e passamos (incluindo o nome, o caminho do programa e variáveis de ambiente) uma quantidade de argumentos que supere o definido em ARG_MAX o programa é terminado com a seguinte mensagem:

shell: comando: Argument list too long

Vamos simular este comportamento criando uma grande quantidade de arquivos em um diretório. O número de arquivos que precisam ser criados pode variar de acordo com o tamanho definido em ARG_MAX.

$ for i in $(seq 1 50000); do touch $i; done
$ rm *
bash: /bin/rm: Argument list too long
$ ls *
bash: /bin/ls: Argument list too long
$ mv * /tmp/
/bin/bash: /bin/mv: Argument list too long
$ grep a *
bash: /bin/grep: Argument list too long
$ chmod 555 *
bash: /bin/chmod: Argument list too long

Existem várias maneiras de contornar este “problema”. Serão listadas algumas:

$ find . -name '*' -print0 | xargs -0 rm
$ find . -type f -print0 | xargs -0 rm
$ find . -type f -exec rm {} \\;
$ echo * | xargs rm

Dica: usando o xargs é mais rápido!

Um leitor mais atendo notaria que a última solução apresentada não poderia funcionar, já que o * utilizado seria expandido para todos os arquivos e excederia o tamanho definido em ARG_MAX.

O echo é um comando builtin do shell, ou seja, um novo programa não é executado (chamada de sistema exec não é invocada). Se utilizarmos o comando echo do sistema operacional o erro será mostrado:

$ /bin/echo *
bash: /bin/echo: Argument list too long
$ echo *
lista de todos os arquivos do diretório

A solução com echo não funciona se existir espaços em branco no nome dos arquivos.

This entry was posted in Shell. Bookmark the permalink.

2 Responses to Shell: Erro: Argument list too long

  1. Gustavo Chaves says:

    Seria legal explicar que as versões com o xargs são mais rápidas que a versão com o “-exec” do find porque a do -exec vai executar um “rm” pra remover cada arquivo enquanto as que usam xargs vão executar um “rm” pra cada lista de arquivos que caibam sem estourar uma linha de comando.

    A primeira versão (find . -name ‘*’ -print0 | xargs -0 rm) vai passar o diretório corrente “.” e qualquer outro subdiretório do diretório corrente para o rm, o que vai gerar algumas mensagens de erro inócuas. A segunda versão me parece mais interessante.

    O “truque” do echo builtin é bem interessante, mas vale a pena ressaltar que nem todas as shells possuem esta builtin. Algumas delas usam o comando /bin/echo. Portanto, acho melhor evitar este tipo de comando num script. Há, também, uma diferença em relação às versões com o find. O “echo *” não ecoa os arquivos com nomes que comecem com ponto. Já o find sim. Isso pode gerar dúvidas.

    Na minha opinião, a melhor alternativa, por ser a mais geral e mais eficiente, é a segunda: find . -type f -print0 | xargs -0 rm.

    Gustavo.

  2. Josiana Cavalcanti says:

    Gustavo,

    Simplesmente perfeito! Executei o comando e excluiu tudo do diretório.

    Obrigada pela dica!

Comments are closed.