1001Ferramentas
🔍Geradores

Gerador de find

Construa comandos find por nome, tipo, tamanho, idade e -exec/-delete. Útil para varreduras em scripts shell.


  

find em profundidade: testes, ações e os operadores que costuram tudo

O find é o caminhador canônico do Unix — um utilitário POSIX mais antigo do que a maioria das linguagens de programação ainda em uso. A forma geral de um comando find é find [caminhos...] [testes] [ações]: os caminhos dizem onde olhar, os testes filtram os candidatos e as ações dizem o que fazer com os matches. Sem ação explícita, o find se comporta como se você tivesse escrito -print. Este gerador combina os testes mais comuns; as seções abaixo explicam o resto, que você pode acrescentar à mão.

Diferente do ls, o find percorre a árvore em profundidade e avalia cada entrada contra a expressão. Testes e ações não são fases separadas — são primárias que retornam verdadeiro/falso, ligadas por AND implícito. Quando isso entra na cabeça, comandos exóticos como find . -name '*.log' -mtime +30 -delete deixam de ser mágica: é só um AND lógico entre três primárias.

Os testes mais comuns

  • -name 'padrão' — glob de shell aplicado apenas ao nome do arquivo (basename). Case-sensitive. Sempre coloque entre aspas para o shell não expandir antes.
  • -iname 'padrão' — variante case-insensitive de -name.
  • -path 'padrão' / -wholename — glob sobre o caminho completo relativo (ótimo para "arquivos em **/test/**").
  • -type — tipo do arquivo: f arquivo regular, d diretório, l symlink, b block device, c char device, p named pipe (FIFO), s socket.
  • -size — tamanho. Sufixos: c bytes, k KiB, M MiB, G GiB. Prefixos +/- para maior/menor que. Exemplos: -size +100M, -size -1k.
  • -mtime N — modificado há N*24 h. -mtime -7 = nos últimos 7 dias, -mtime +30 = mais antigo que 30 dias. Família: -atime (acesso) e -ctime (mudança de inode).
  • -mmin N — mesma ideia em minutos (-mmin -60 = tocado na última hora).
  • -perm 644 — modo exato. -perm -u+w = pelo menos write do dono. -perm /u+x,g+x = qualquer um desses bits.
  • -user nome, -group nome — match por dono.
  • -empty — arquivos regulares e diretórios vazios.
  • -newer arquivo — modificado mais recentemente que arquivo. Útil em build incremental.

Operadores lógicos e agrupamento

Os testes são ligados por AND por padrão. Use -or (ou -o) para OR e -not (ou !) para negação. Agrupe com parênteses escapados, porque parênteses são metacaracteres do shell:

# Todos os .bak OU .tmp, apagados
find . \( -name '*.bak' -o -name '*.tmp' \) -delete

# Arquivos regulares fora de node_modules
find . -type f ! -path '*/node_modules/*'

Para excluir diretórios inteiros sem entrar neles, prefira -prune a !: ele evita que o find desça na subárvore, o que é muito mais rápido em árvores grandes: find . -type d -name node_modules -prune -o -type f -print.

Ações: -print, -delete, -exec e xargs

  • -print — padrão. Um match por linha, separado por newline. Quebra se o nome de arquivo tiver newline.
  • -print0 — separa por NUL, desenhado para xargs -0. Robusto contra nomes esquisitos.
  • -delete — apaga os matches. Sem confirmação, sem lixeira. Rode com -print antes.
  • -exec cmd {} \; — executa cmd uma vez por match. Portável, mas lento em grandes resultados por causa do fork.
  • -exec cmd {} + — agrupa os matches numa única invocação, muito mais rápido. Comportamento parecido com xargs.
  • -ok cmd {} \; — como -exec, mas pergunta antes de cada chamada. Útil para operações destrutivas.
# Apaga logs com mais de 30 dias
find /var/log -name '*.log' -mtime +30 -delete

# Grep em vários arquivos com segurança (espaços, newlines)
find . -type f -print0 | xargs -0 grep -l "TODO"

# Procura binários suid (auditoria de segurança)
find / -perm -4000 -type f 2>/dev/null

# Tamanho total dos .mp4
find . -name '*.mp4' -print0 | du -ch --files0-from=- | tail -1

find vs alternativas modernas

  • fd (fd-find) — reescrita em Rust com foco em ergonomia: smart-case, respeita gitignore, paraleliza e usa cor. fd '\.log$' ganha de find . -name '*.log' em 90% dos usos interativos.
  • ripgrep (rg) — quando você quer mesmo é grepar conteúdo, o rg é uma a duas ordens de magnitude mais rápido que find ... | xargs grep.
  • locate / mlocate / plocate — consulta um índice pré-construído do filesystem. Instantâneo, mas só tão fresco quanto o último updatedb.
  • eza / exals moderno com árvore e status de git; não é busca, mas costuma ser o que a pessoa realmente queria.

FAQ

Por que o find é lento em árvores enormes? Ele percorre todos os inodes e não usa índice. Para consultas repetidas na mesma árvore, monte um índice com updatedb e use locate, ou troque por fd, que paraleliza o walk.

-exec {} + ou pipe pro xargs — qual é mais rápido? Os dois agrupam matches em poucas invocações e ficam a poucos pontos percentuais um do outro. xargs -0 com -print0 é mais flexível (paralelismo com -P, posição customizada do {}); -exec ... + é mais portável e não tem problema de quoting.

Como buscar case-insensitive? Use -iname, -ipath, -iregex. São extensões GNU, mas o BSD find do macOS também suporta.

Por que find . -name *.txt falha com "paths must precede expression"? O shell expandiu *.txt nos nomes do diretório atual antes do find ver o argumento. Use aspas: find . -name '*.txt'.

Qual a diferença entre -name e -path? -name casa apenas com o último segmento (basename); -path casa com o caminho relativo inteiro. Para "qualquer .js dentro de src/", use -path '*/src/*' -name '*.js'.

Ferramentas Relacionadas