você está aqui: Home  → Colunistas  →  Cantinho do Shell

 

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.

Recomende este artigo nas redes sociais

 

 

Veja a relação completa dos artigos desta coluna