você está aqui: Home  → Arquivo de Mensagens

bash - Argument list too long

Colaboração: Daniel Duclos

Data de Publicação: 15 de Junho de 2007

Pode ser que você já tenha tentado dar um comando usando o asterisco * na bash e tenha obtido este erro:

  bash: comando: Argument list too long

Aonde comando pode ser um rm, ou um cp, ou qualquer outro. Por exemplo:

  daniduc@nicholas:~/teste$ rm -f *
  bash: /bin/rm: Argument list too long
  daniduc@nicholas:~/teste$

Quem imprimiu esse erro não foi o comando (o rm, no exemplo), mas a bash, que é responsável por expandir o wildcard *, substituindo-o pela lista de arquivos no diretório. Em sistemas UNIX, há um limite fixo de memória reservado para o ambiente e lista de parâmetros de um comando. No caso do meu servidor Linux, esse limite é 128K, mas isso varia de sistema para sistema. Você pode descobrir no seu sistema usando o comando getconf. Veja:

  daniduc@nicholas:~/teste$ getconf ARG_MAX
  131072
  daniduc@nicholas:~/teste$

Agora, ao que interessa. Como fazer para remover os arquivos do meu exemplo acima? Existem diversas saídas, variando a eficiência dependendo de qual é o seu comando, na verdade. Mas vamos ver o rm, pois o exemplo dele pode ser aplicado a outros, como por exemplo o cp, ou o mv.

Se você puder eliminar o diretório inteiro no qual estão os arquivos, não há problemas:

  daniduc@nicholas:~$ rm -rf teste/
  daniduc@nicholas:~$

Se você só pode eliminar os arquivos, uma saída é usar o comando find.

  daniduc@nicholas:~/teste$ find . -type f -exec rm -f {} \;
  daniduc@nicholas:~/teste$

Nesse caso, eu pedi para o find encontrar no diretório em que estou (.) todos os arquivos (-type f) e para cada um deles executar (-exec) o comando rm. As chaves {} são substituídas por cada arquivo encontrado pelo find. Dessa forma o rm é executado uma vez para cada arquivo, tendo assim apenas aquele arquivo como parâmetro, o que evita ultrapassar o limite de memória imposto. O final \; é para fechar o comando do -exec com um ponto e vírgula, que precisa ser precedido da contra barra (\) para que a bash não o interprete (uma vez que ; é um caractere com sentido especial para a bash) e apenas o passe para o find.

Caso, por exemplo, você precise remover somente os arquivos html e não os arquivos .php em um diretório, basta usar o find novamente:

  daniduc@nicholas:~/teste$ ls *.php
  1.php 2.php
  daniduc@nicholas:~/teste$ ls
  (saida resumida:)
  23497.html 36998.html 50498.html 6399.html 774.html 9.html
  23498.html 36999.html 50499.html 639.html 77500.html
  23499.html 3699.html 5049.html 63.html 77501.html
  2349.html 369.html 504.html 64000.html 77502.html
  234.html 36.html 50500.html 64001.html 77503.html
  daniduc@nicholas:~/teste$ find . -name \*.html -exec rm -f {} \;
  daniduc@nicholas:~/teste$ ls
  1.php 2.php
  daniduc@nicholas:~/lixo

Aqui o asterisco funciona porque está precedido pela contrabarra o que faz com que a bash não o interprete, apenas o find. E o find não expande o asterisco em todos os arquivos do diretório, como a bash. Para o find, o asterisco é parte de uma expressão regular, que quer dizer encontre arquivos cujo nome seja qualquer coisa seguida de um .html .

Eu uso a versão da GNU do find, presente na maioria dos sistemas Linux. Caso o seu find não entenda o parâmetro -exec, use-o em conjunto com comando xargs:

  daniduc@nicholas:~/teste$ find . -name \*.html | xargs rm -f
  daniduc@nicholas:~/teste$ ls
  1.php 2.php
  daniduc@nicholas:~/teste$

Referências:

http://www.gnu.org/software/coreutils/faq/coreutils-faq.html#Argument-list-too-long

Essa dica foi publicada também no Blog UNIX Notes, que mantenho em conjunto com minha esposa.



Veja a relação completa dos artigos de Daniel Duclos

 

 

Opinião dos Leitores

CArlos
28 Out 2011, 17:04
Obrigado! me ajudou muito!
Mélory
24 Mai 2011, 09:17
No meu caso queria contar quantos arquivos tinha de determinada extensão, e funcionou assim:
find . -name \*.html | wc -l
Rod Elias
08 Set 2010, 16:22
Artigo muito bem explicado e muito útil.
Já me ajudou em algumas situações semelhantes.
Obrigado.
*Nome:
Email:
Me notifique sobre novos comentários nessa página
Oculte meu email
*Texto:
 
  Para publicar seu comentário, digite o código contido na imagem acima
 


Powered by Scriptsmill Comments Script