De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.

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.

Adicionar comentário

* Campos obrigatórios
5000
Powered by Commentics

Comentários

Nenhum comentário ainda. Seja o primeiro!


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