Como usar o find e locate para localizar arquivos no Linux

Introdução

Um problema comum de usuários ao utilizar uma máquina Linux pela primeira vez é como localizar os arquivos que eles estão procurando.

Este guia irá abordar como usar o comando find nomeado apropriadamente. Isso irá ajudar a pesquisar arquivos em seu VPS usando uma variedade de filtros e parâmetros. Vamos também abordar brevemente o comando locate, que pode ser usado para localizar arquivos de outra forma.

Pesquisando por nome

A maneira mais óbvia de localizar arquivos é pelo nome.

Para encontrar um arquivo pelo nome, digite:

  • find -name "query"

O comando diferencia letras maiúsculas de minúsculas, o que significa que pesquisar por file é diferente de pesquisar por File.

Para encontrar um arquivo pelo nome, mas não diferenciar maiúsculas de minúsculas, digite:

  • find -iname "query"

Se quiser encontrar todos os arquivos que não aderem a um padrão específico, inverta a pesquisa com -not ou !. Se você usar !, é necessário adicionar um caractere de escape para que o bash não tente interpretá-lo antes do comando find agir:

  • find -not -name "query_to_avoid"

ou

  • find ! -name "query_to_avoid"

Pesquisando por tipo

É possível especificar o tipo de arquivo que deseja encontrar com o parâmetro -type. Funciona desta forma:

  • find -type type_descriptor query

Alguns dos descritores mais comuns que você pode usar para especificar o tipo de arquivo estão aqui:

  • f: arquivo regular

  • d: diretório

  • l: link simbólico

  • c: dispositivos de caracteres

  • b: dispositivos de bloqueio

Por exemplo, se quisermos encontrar todos os dispositivos de caracteres em nosso sistema, emitimos este comando:

  • find / -type c
Output/dev/parport0 /dev/snd/seq /dev/snd/timer /dev/autofs /dev/cpu/microcode /dev/vcsa7 /dev/vcs7 /dev/vcsa6 /dev/vcs6 /dev/vcsa5 /dev/vcs5 /dev/vcsa4 . . . 

Podemos pesquisar todos os arquivos que terminam em .conf desta forma:

  • find / -type f -name "*.conf"
Output/var/lib/ucf/cache/:etc:rsyslog.d:50-default.conf /usr/share/base-files/nsswitch.conf /usr/share/initramfs-tools/event-driven/upstart-jobs/mountall.conf /usr/share/rsyslog/50-default.conf /usr/share/adduser/adduser.conf /usr/share/davfs2/davfs2.conf /usr/share/debconf/debconf.conf /usr/share/doc/apt-utils/examples/apt-ftparchive.conf . . . 

Filtrando por tempo e tamanho

O comando find oferece várias maneiras de filtrar resultados por tamanho e tempo.

Tamanho

É possível filtrar por tamanho usando o parâmetro -size.

Adicionamos um sufixo no final do nosso valor que especifica como estamos contando. Estas são algumas opções populares:

  • c: bytes

  • k: Kilobytes

  • M: Megabytes

  • G: Gigabytes

  • b: blocos de 512 bytes

Para encontrar todos os arquivos que possuem exatamente 50 bytes, digite:

  • find / -size 50c

Para encontrar todos os arquivos com menos de 50 bytes, usamos esta forma:

  • find / -size -50c

Para encontrar todos os arquivos com mais de 700 Megabytes, usamos este comando:

  • find / -size +700M

Tempo

O Linux armazena dados de tempo sobre o horário de acesso, horário de modificação e horário de alteração.

  • Horário de acesso: horário da última vez que um arquivo foi lido ou escrito.

  • Horário de modificação: horário da última vez que o conteúdo do arquivo foi modificado.

  • Horário de alteração: horário da última vez que os meta-dados do inode do arquivo foram alterados.

Podemos usá-los com os parâmetros -atime, -mtime e -ctime. Eles podem usar os símbolos + e – para especificar maior que ou menor que, como fizemos com o tamanho.

O valor deste parâmetro especifica quantos dias atrás você gostaria de pesquisar.

Para encontrar arquivos que possuem um horário de modificação de um dia atrás, digite:

  • find / -mtime 1

Se quisermos arquivos que foram acessados há menos de um dia, digitamos:

  • find / -atime -1

Para obter arquivos que tiveram seus metadados alterados há mais de 3 dias, digite:

  • find / -ctime +3

Existem também alguns parâmetros complementares que podem ser usados para especificar minutos em vez de dias:

  • find / -mmin -1

Isso irá encontrar os arquivos que foram modificados no sistema no último minuto.

O find também é capaz de fazer comparações com um arquivo de referência e retornar as que são mais novas:

  • find / -newer myfile

Pesquisando por proprietário e permissões

Também é possível pesquisar arquivos pelo proprietário do arquivo ou proprietário do grupo.

Isso é feito usando os parâmetros -user e -group respectivamente. Encontre um arquivo de propriedade do usuário “syslog” digitando:

  • find / -user syslog

Da mesma forma, é possível especificar arquivos de propriedade do grupo “shadow” digitando:

  • find / -group shadow

Também podemos pesquisar arquivos com permissões específicas.

Se quisermos que haja correspondência com um conjunto específico de permissões, usamos esta forma:

  • find / -perm 644

Isso irá encontrar arquivos com as permissões especificadas.

Se quisermos especificar qualquer coisa com pelo menos essas permissões, use esta forma:

  • find / -perm -644

Isso irá encontrar qualquer arquivo correspondente que tenha permissões adicionais. Neste caso, um arquivo com permissões de “744” seria correspondente.

Filtrando por profundidade

Para esta seção, iremos criar uma estrutura de diretório em um diretório temporário. Ela irá conter três níveis de diretórios, com dez diretórios no primeiro nível. Cada diretório (incluindo o diretório temporário) irá conter dez arquivos e dez subdiretórios.

Crie essa estrutura emitindo os seguintes comandos:

  • cd
  • mkdir -p ~/test/level1dir{1..10}/level2dir{1..10}/level3dir{1..10}
  • touch ~/test/{file{1..10},level1dir{1..10}/{file{1..10},level2dir{1..10}/{file{1..10},level3dir{1..10}/file{1..10}}}}
  • cd ~/test

Sinta-se livre para verificar as estruturas de diretório com ls e cd para entender melhor como as coisas estão organizadas. Quando terminar, retorne ao diretório de teste:

  • cd ~/test

Iremos estudar como retornar arquivos específicos dessa estrutura. Vamos testar primeiro um exemplo com apenas uma pesquisa regular de nomes, para comparação:

  • find -name file1
Output./level1dir7/level2dir8/level3dir9/file1 ./level1dir7/level2dir8/level3dir3/file1 ./level1dir7/level2dir8/level3dir4/file1 ./level1dir7/level2dir8/level3dir1/file1 ./level1dir7/level2dir8/level3dir8/file1 ./level1dir7/level2dir8/level3dir7/file1 ./level1dir7/level2dir8/level3dir2/file1 ./level1dir7/level2dir8/level3dir6/file1 ./level1dir7/level2dir8/level3dir5/file1 ./level1dir7/level2dir8/file1 . . . 

Há muitos resultados. Se canalizarmos o resultado para um contador, vemos que há um total de 111 resultados:

  • find -name file1 | wc -l
Output1111 

Provavelmente, esse número de resultados é grande de mais para lhe ser útil na maioria dos casos. Vamos tentar restringi-lo.

Especifique a profundidade máxima da pesquisa no diretório de pesquisa de nível superior:

  • find -maxdepth num -name query

Para encontrar “file1” apenas nos diretórios de “nível 1”, especifique uma profundidade máxima de 2 (1 para o diretório de nível superior e 1 para os diretórios de nível 1):

  • find -maxdepth 2 -name file1
Output./level1dir7/file1 ./level1dir1/file1 ./level1dir3/file1 ./level1dir8/file1 ./level1dir6/file1 ./file1 ./level1dir2/file1 ./level1dir9/file1 ./level1dir4/file1 ./level1dir5/file1 ./level1dir10/file1 

Essa é uma lista muito mais gerenciável.

Também é possível especificar um diretório mínimo se souber que todos os arquivos existem depois de um determinado ponto abaixo do diretório atual:

  • find -mindepth num -name query

Podemos usar isso para encontrar apenas os arquivos no final das ramificações de diretório:

  • find -mindepth 4 -name file
Output./level1dir7/level2dir8/level3dir9/file1 ./level1dir7/level2dir8/level3dir3/file1 ./level1dir7/level2dir8/level3dir4/file1 ./level1dir7/level2dir8/level3dir1/file1 ./level1dir7/level2dir8/level3dir8/file1 ./level1dir7/level2dir8/level3dir7/file1 ./level1dir7/level2dir8/level3dir2/file1 . . . 

Novamente, devido à nossa estrutura de diretórios ramificada, isso irá retornar um grande número de resultados (1000).

É possível combinar os parâmetros de profundidade mínima e máxima para se concentrar em um intervalo estreito:

  • find -mindepth 2 -maxdepth 3 -name file
Output./level1dir7/level2dir8/file1 ./level1dir7/level2dir5/file1 ./level1dir7/level2dir7/file1 ./level1dir7/level2dir2/file1 ./level1dir7/level2dir10/file1 ./level1dir7/level2dir6/file1 ./level1dir7/level2dir3/file1 ./level1dir7/level2dir4/file1 ./level1dir7/file1 . . . 

Executando e combinando comandos find

É possível executar um comando auxiliar arbitrário em tudo o que for encontrado pelo find usando o parâmetro -exec. Isso é chamado desta forma:

  • find find_parameters -exec command_and_params {} ;

O {} é usado como espaço reservado para os arquivos que encontram correspondências. O ; é usado para que o comando find saiba onde o comando termina.

Por exemplo, poderíamos encontrar os arquivos na seção anterior que possuía permissões 644 e modificá-los para possuir permissões 664:

  • cd ~/test
  • find . -type f -perm 644 -exec chmod 664 {} ;

Em seguida, poderíamos alterar as permissões de diretório desta forma:

  • find . -type d -perm 755 -exec chmod 700 {} ;

Se quiser encadear diferentes resultados juntos, use os comandos -and ou -or. O -and é considerado caso seja omitido.

  • find . -name file1 -or -name file9

Pesquisar arquivos usando o locate

Uma alternativa ao find é o comando locate. Esse comando é geralmente mais rápido e pode pesquisar todo o sistema de arquivos com facilidade.

É possível instalar o comando no Debian ou no Ubuntu com o apt:

  • sudo apt install mlocate

No CentOS, use o dnf:

  • sudo dnf install mlocate

A razão pela qual o locate é mais rápido que o find é porque ele depende de um banco de dados dos arquivos no sistema de arquivos.

O banco de dados é geralmente atualizado uma vez por dia com um script cron, mas é possível atualizá-lo manualmente digitando:

  • sudo updatedb

Execute este comando agora. Lembre-se, o banco de dados deve estar sempre atualizado caso você queira encontrar arquivos recentemente adquiridos ou criados.

Para encontrar arquivos com o locate, use esta sintaxe:

  • locate query

É possível filtrar o resultado de algumas maneiras.

Por exemplo, para retornar apenas arquivos que contêm a própria consulta, em vez de retornar cada arquivo que possui a consulta nos diretórios que levam a ele, é possível usar o -b para pesquisar apenas o “nome base”:

  • locate -b query

Para localizar apenas os resultados de retorno que ainda existem no sistema de arquivos (que não foram removidos entre a última chamada de updatedb e a chamada locate atual), utilize o sinalizador -e:

  • locate -e query

Para ver estatísticas sobre as informações que o locate catalogou, use a opção -S:

  • locate -S
OutputDatabase /var/lib/mlocate/mlocate.db: 3,315 directories 37,228 files 1,504,439 bytes in file names 594,851 bytes used to store database 

Conclusão

Tanto o find quanto o locate representam boas maneiras de encontrar arquivos em seu sistema. Cabe a você decidir qual dessas ferramentas é apropriada em cada situação.

O find e o locate são comandos poderosos que podem ser fortalecidos combinando-os com outros utilitários ao longo das pipelines. Experimente filtrar usando comandos como wc, sort e grep.