find - Procurando arquivo por características
Por Julio Cezar Neves
O comando find é muito badalado e bastante conhecido, porém resolvi assim mesmo postar este artigo no nosso Cantinho do Shell por causa de algumas características pouco conhecidas como a ação printf. Espero que vocês gostem.
Sintaxe
find [caminho ...] expressão [ação]
O comando find procura arquivos pelo nome ou outras características.
Parâmetros
| caminho | Caminhos de diretório a partir do qual irá procurar pelos arquivos; |
| expressão | Define quais critérios de pesquisa. Pode ser uma combinação entre vários tipos de procura; |
| ação | Define que ação executar com os arquivos que atender aos critérios de pesquisa definidos por expressão. |
Os principais critérios de pesquisa definidos por expressão são:
- -name nome Procura arquivos que tenham o nome especificado. Aqui podem ser usados metacaracteres ou caracteres curingas, porém estes caracteres deverão estar entre aspas, apóstrofos ou imediatamente precedidos por uma contrabarra (por enquanto fico devendo esta explicação porque isso será exaustivamente ensinado quando começarmos a programar);
- -iname Idêntico à opção -name. Porém neste caso, ignora maiúsculas e minúsculas. Deve ser usada quando não sabemos se o nome do arquivo possui letras maiúsculas.
- -user usuário Procura arquivos que tenham usuário como dono;
- -group grupo Procura arquivos que tenham grupo como grupo dono;
- -type c Procura por arquivos que tenham o tipo c, correspondente à letra do tipo do arquivo. Os tipos aceitos estão na tabela a seguir:
| Valores de c | Tipo de arquivo procurado |
| b | Arquivo especial acessado a bloco |
| c | Arquivo especial acessado a caractere |
| d | Diretório |
| p | Named pipe (FIFO) |
| f | Arquivo normal |
| l | Link simbólico |
| s | Socket |
- -size ±n[bckw] Procura por arquivos que usam mais (+n) de n unidades de espaço ou a menos (-n) de n unidades de espaço.
| Unidade | Valor |
| b | Bloco de 512 bytes (valor default) |
| c | Caracteres |
| k | Kilobytes (1024 bytes) |
| w | Palavras (2 bytes) |
| -atime ±d | Procura por arquivos que foram acessados há mais (+d) de d dias ou a menos (-d) de d dias; |
| -ctime ±d | Procura por arquivos cujo status mudou há mais (+d) de d dias ou a menos (-d) de d dias; |
| -mtime ±d | Procura por arquivos cujos dados foram modificados há mais (+d) de d dias ou a menos (-d) de d dias; |
Para usar mais de um critério de pesquisa, faça:
expressão1 expressão2 ou expressão1 -a expressão2 para atender aos critérios especificados por expressão1 e expressão2; expressão1 -o expressão2 para atender aos critérios especificados por expressão1 ou expressão2.
As principais ações definidas para ação são:
- -print Esta opção faz com que os arquivos encontrados sejam exibidos na tela. Esta é a opção default no Linux. Nos outros sabores Unix que conheço, se nenhuma ação for especificada, ocorrerá um erro;
- -exec cmd {} \; Executa o comando
cmd. O escopo de comando é considerado encerrado quando um ponto-e-vírgula (;) é encontrado. A cadeia {} é substituída pelo nome de cada arquivo que satisfaz ao critério de pesquisa e a linha assim formada é executada. Assim como foi dito para a opção name, o ponto-e-vírgula (;) deve ser precedido por uma contrabarra, ou deve estar entre aspas ou apóstrofos; - -ok cmd {} \; O mesmo que o anterior porém pergunta se pode executar a instrução cmd sobre cada arquivo que atende ao critério de pesquisa;
- -printf formato Permite que se escolha os campos que serão listados e formata a saída de acordo com o especificado em formato.
Exemplos
Para listar na tela (-print) todos os arquivos, a partir do diretório corrente, terminados por .sh, faça:
$ find . -name \*.sh Ação não especificada print é default ./undelete.sh ./ntod.sh estes quatro primeiros arquivos foram ./dton.sh encontrados no diretório corrente. ./graph.sh ./tstsh/cotafs.sh ./tstsh/data.sh Estes quatro foram encontrados no ./tstsh/velha.sh diretório tstsh, sob o diretório corrente ./tstsh/charascii.sh
Preciso abrir espaço em um determinado file system com muita urgência, então vou remover arquivos com mais de um megabyte e cujo último acesso foi há mais de 60 dias. Para isso, vou para este file system e faço:
$ find . type f size +1000000c atime +60 exec rm {} \;
Repare que no exemplo acima usei três critérios de pesquisa, a saber:
| -type f | Todos os arquivos regulares (normais) |
| -size +1000000c | Tamanho maior do que 1000000 de caracteres (+1000000c) |
| -atime +60 | Último acesso há mais de 60 (+60) dias. |
Repare ainda que entre estes três critérios foi usado o conector e, isto é, arquivos regulares e maiores que 1MByte e sem acesso há mais de 60 dias.
Para listar todos os arquivos do disco terminados por .sh ou .txt, faria:
$ find / -name \*.sh o name \*.txt print
Neste exemplo devemos realçar além das contrabarras (\) antes dos asteriscos (*), o uso do o para uma ou outra extensão e que o diretório inicial era o raiz (/); assim sendo, esta pesquisa deu-se no disco inteiro (o que freqüentemente é bastante demorado).
Com o printf é possível formatar a saída do comando find e especificar os dados desejados. A formatação do printf é muito semelhante à do mesmo comando na linguagem C e interpreta caracteres de formatação precedidos por um símbolo de percentual (%). Vejamos seus efeitos sobre a formatação:
| Caractere | Significado |
| %f | Nome do arquivo (caminho completo não aparece) |
| %F | Indica a qual tipo de file system o arquivo pertence |
| %g | Grupo ao qual o arquivo pertence |
| %G | Grupo ao qual o arquivo pertence (GID- Numérico) |
| %h | Caminho completo do arquivo (tudo menos o nome) |
| %i | Número do inode do arquivo (em decimal) |
| %m | Permissão do arquivo (em octal) |
| %p | Nome do arquivo |
| %s | Tamanho do arquivo |
| %u | Nome de usuário (username) do dono do arquivo |
| %U | Número do usuário (UID) do dono do arquivo |
Também é possível formatar datas e horas obedecendo às tabelas a seguir:
| Caractere | Significado |
| %a | Data do último acesso |
| %c | Data de criação |
| %t | Data de alteração |
Os três caracteres anteriores produzem uma data semelhante ao do comando date.
Veja um exemplo:
$ find . -name ".b*" -printf '%t %p\n' Mon Nov 29 11:18:51 2004 ./.bash_logout Tue Nov 1 09:44:16 2005 ./.bash_profile Tue Nov 1 09:45:28 2005 ./.bashrc Fri Dec 23 20:32:31 2005 ./.bash_history
Nesse exemplo, o %p foi o responsável por colocar os nomes dos arquivos. Caso fosse omitido, somente as datas seriam listadas.
Observe ainda que ao final foi colocado um /n. Sem ele não haveria salto de linha e a listagem anterior seria uma grande tripa.
Essas datas também podem ser formatadas, para isso basta passar as letras da tabela anterior para maiúsculas (%A, %C e %T) e usar um dos formatadores das duas tabelas a seguir:
Tabela de formatação de tempo
| Caractere | Significado |
| H | Hora (00..23) |
| I | Hora (01..12) |
| k | Hora (0..23) |
| l | Hora (1..12) |
| M | Minuto (00..59) |
| p | AM or PM |
| r | Horário de 12 horas (hh:mm:ss) seguido de AM ou PM |
| S | Segundos (00 ... 61) |
| T | Horário de 24-horas (hh:mm:ss) |
| Z | Fuso horário (na Cidade Maravilhosa BRST) |
Tabela de formatação de datas
| Caractere | Significado |
| a | Dia da semana abreviado (Dom...Sab) |
| A | Dia da semana por extenso (Domingo...Sábado) |
| b | Nome do mês abreviado (Jan...Dez) |
| B | Dia do mês por extenso (Janeiro...Dezembro) |
| c | Data e hora completa (Fri Dec 23 15:21:41 2005) |
| d | Dia do mês (01...31) |
| D | Data no formato mm/dd/aa |
| h | Idêntico a b |
| j | Dia seqüencial do ano (001366) |
| m | Mês (01...12) |
| U | Semana seqüencial do ano. Domingo como 1º dia da semana (00...53) |
| w | Dia seqüencial da semana (0..6) |
| W | Semana seqüencial do ano. Segunda-feira como 1º dia da semana (00...53) |
| x | Representação da data no formato do país (definido por $LC_ALL) |
| y | Ano com 2 dígitos (00...99) |
| Y | Ano com 4 dígitos |
Para melhorar a situação, vejamos uns exemplos; porém, vejamos primeiro quais são os arquivos do diretório corrente que começam por .b:
$ ls -la .b* -rw------- 1 d276707 ssup 21419 Dec 26 17:35 .bash_history -rw-r--r-- 1 d276707 ssup 24 Nov 29 2004 .bash_logout -rw-r--r-- 1 d276707 ssup 194 Nov 1 09:44 .bash_profile -rw-r--r-- 1 d276707 ssup 142 Nov 1 09:45 .bashrc
Para listar esses arquivos em ordem de tamanho, podemos fazer:
$ find . -name ".b*" -printf '%s\t%p\n' | sort -n 24 ./.bash_logout 142 ./.bashrc 194 ./.bash_profile 21419 ./.bash_history
No exemplo que acabamos de ver, o \t foi substituído por um <TAB> na saída de forma a tornar a listagem mais legível. Para listar os mesmos arquivos classificados por data e hora da última alteração:
$ find . -name ".b*" -printf '%TY-%Tm-%Td %TH:%TM:%TS %p\n' | sort 2004-11-29 11:18:51 ./.bash_logout 2005-11-01 09:44:16 ./.bash_profile 2005-11-01 09:45:28 ./.bashrc 2005-12-26 17:35:13 ./.bash_history
Espero que o texto tenha sido útil.
Veja a relação completa dos artigos da coluna Cantinho do Shell
Para se manter atualizado sobre as novidades desta coluna, consulte sempre o newsfeed RSS
Para saber mais sobre RSS, leia o artigo O Padrão RSS - A luz no fim do túnel.
Opinião dos Leitores
18 Nov 2011, 07:30
Caractere Significado
%a Data do último acesso
%c Data de criação
%t Data de alteração
Sendo que o correto, segundo o proprio man do find seria:
Caractere Significado
%a Data do último acesso
%c Data de alteração ( change)
%t Data da modificação ( last modification )
10 Mar 2009, 20:09
Fernando Marques
05 Ago 2008, 08:23
Imagine se você desejasse explorar outras funções né afinal o cara é o cara.
Show de bola Julio me ajudou pakas e irá quebrar um galhão em meu dia-a-dia.
Abraços
21 Jul 2008, 20:11
ontem na prova discursiva do concurso do BNDES caiu uma questão que a resposta era o comando find. Se seu artigo sai antes muita gente tinha acertado esta. :)
[]s
Carlos
21 Jul 2008, 12:59
21 Jul 2008, 09:21
não tentei fazer um tratado sobre o find, até pq esta cmd é bastante conhecido. A minha intenção era ir fundo na ação printf, por não existir no *não* GNU find (Unix), pelos seus caracteres de formatação serem diferentes do cmd printf tradicional e ainda pq já me quebrou um galhão.
Espero ter cumprido o meu intento...
21 Jul 2008, 02:28
Ficou ótimo o artigo. Parabéns.



