Corrigindo "Argument list too long" -- Quando rm * e comandos similares falham
O que este artigo aborda
- Por que
rm *ecp * dest/falham com "Argument list too long" - Como processar grandes quantidades de arquivos com segurança usando
find + xargsefind -delete - Como lidar com nomes de arquivo com espaços ou caracteres especiais
Correção rápida
# Substituto para rm * -- abordagem mais segura find . -maxdepth 1 -name "*.log" -type f -delete # Ou via xargs find . -maxdepth 1 -name "*.log" -print0 | xargs -0 rm
Por que "Argument list too long" acontece?
Quando você executa rm *, o shell (não o rm) expande o wildcard primeiro. Com dezenas de milhares de arquivos, a lista de argumentos resultante excede o limite do kernel ARG_MAX, e o kernel retorna um erro E2BIG.
$ rm *.log -bash: /bin/rm: Argument list too long
Verifique o ARG_MAX do seu sistema:
$ getconf ARG_MAX 2097152
2097152
O valor típico no Linux é 2 MB (2.097.152 bytes). Quando o comprimento total de todos os argumentos expandidos excede esse valor, o comando falha.
Este erro afeta qualquer comando que use wildcards: ls *.log, cp *.log dest/, cat *.txt, chmod 644 *.php, e assim por diante.
find processa arquivos um de cada vez e nunca constrói uma lista completa de argumentos para exec(), por isso contorna esse limite completamente.
Correção com find -delete
Para exclusão, find -delete é a opção mais simples e segura -- não precisa de xargs.
find . -maxdepth 1 -name "*.log" -type f -delete
-maxdepth 1: apenas o diretório atual (escopo equivalente arm *)-type f: apenas arquivos (evita exclusão acidental de diretórios)-delete: exclui cada correspondência
Para incluir subdiretórios, remova -maxdepth:
find /path/to/dir -name "*.log" -type f -delete
Antes de excluir, verifique o que será removido:
# Visualizar correspondencias e contar find . -maxdepth 1 -name "*.log" -type f find . -maxdepth 1 -name "*.log" -type f | wc -l
Correção com find + xargs
Um padrão de uso geral que funciona com qualquer comando, não apenas rm.
Padrão básico
find . -maxdepth 1 -name "*.log" | xargs rm
xargs divide automaticamente os argumentos em lotes para ficar dentro do ARG_MAX.
Nomes de arquivo com espaços ou caracteres especiais
O xargs padrão divide por espaços em branco, o que quebra nomes de arquivo contendo espaços. Use -print0 com xargs -0 (delimitado por NUL) para segurança total:
find . -maxdepth 1 -name "*.log" -print0 | xargs -0 rm
Usar -print0 | xargs -0 como padrão é o hábito mais seguro.
Execução paralela para velocidade
find . -name "*.log" -print0 | xargs -0 -P4 rm
-P4 executa 4 processos em paralelo. Útil ao excluir um número muito grande de arquivos.
Correção para cp / mv
O mesmo erro E2BIG aparece com cp * dest/ e mv * dest/.
# cp
find . -maxdepth 1 -name "*.log" -print0 | xargs -0 -I{} cp {} /dest/
# mv
find . -maxdepth 1 -name "*.log" -print0 | xargs -0 -I{} mv {} /dest/-I{} substitui cada caminho em {}.
Você também pode usar -exec:
find . -maxdepth 1 -name "*.log" -exec cp {} /dest/ \;-exec inicia um processo por arquivo, então xargs é mais rápido para grandes quantidades.
Correção com loop de shell
Uma alternativa simples quando find não está disponível, ou quando você precisa revisar cada arquivo antes de agir.
for f in *.log; do
rm "$f"
doneO shell invoca rm uma vez por arquivo, então ARG_MAX nunca é atingido.
Sempre coloque "$f" entre aspas. Sem as aspas, nomes de arquivo com espaços farão o loop quebrar.
Resumo
| Abordagem | Exemplo | Melhor para |
|---|---|---|
find -delete |
find . -name "*.log" -type f -delete |
Apenas exclusão (mais simples) |
find | xargs rm |
find . -name "*.log" | xargs rm |
Exclusão padrão |
-print0 | xargs -0 |
find . -name "*.log" -print0 | xargs -0 rm |
Nomes com caracteres especiais |
| Loop de shell | for f in *.log; do rm "$f"; done |
Revisão passo a passo |
-exec |
find . -name "*.log" -exec cp {} /dest/ \; |
Operações além de exclusão |
Fluxo de decisão
- Excluindo arquivos ->
find -delete - Copiando ou movendo ->
find ... -print0 | xargs -0 comando - Revisar cada arquivo -> loop de shell