encontrar (Unix) - find (Unix)

achar
Autor (es) original (is) Dick Haight
Desenvolvedor (s) AT&T Bell Laboratories
Sistema operacional Unix , semelhante ao Unix , IBM i
Plataforma Plataforma cruzada
Modelo Comando
Licença findutils : GPLv3 +

No tipo Unix e em alguns outros sistemas operacionais , findé um utilitário de linha de comando que localiza arquivos com base em alguns critérios especificados pelo usuário e imprime o nome do caminho de cada objeto correspondente ou, se outra ação for solicitada, executa essa ação em cada objeto correspondente .

Ele inicia uma pesquisa a partir de um local de partida desejado e, em seguida, percorre recursivamente os nós (diretórios) de uma estrutura hierárquica (normalmente uma árvore ). find pode percorrer e pesquisar em diferentes sistemas de arquivos de partições pertencentes a um ou mais dispositivos de armazenamento montados sob o diretório inicial.

Os critérios de pesquisa possíveis incluem um padrão para corresponder ao nome do arquivo ou um intervalo de tempo para corresponder ao tempo de modificação ou tempo de acesso do arquivo. Por padrão, findretorna uma lista de todos os arquivos abaixo do diretório de trabalho atual , embora os usuários possam limitar a pesquisa a qualquer número máximo desejado de níveis no diretório inicial.

Os locateprogramas relacionados usam um banco de dados de arquivos indexados obtidos por meio find(atualizados em intervalos regulares, geralmente por crontrabalho) para fornecer um método mais rápido de pesquisa de arquivos por nome em todo o sistema de arquivos.

História

findapareceu na versão 5 do Unix como parte do projeto Programmer's Workbench e foi escrito por Dick Haight junto com o cpio , que foram projetados para serem usados ​​juntos.

A implementação do GNU find foi originalmente escrita por Eric Decker. Posteriormente, foi aprimorado por David MacKenzie, Jay Plett e Tim Wood.

O comando find também foi transferido para o sistema operacional IBM i .

Encontrar sintaxe

$ find [-H|-L] path... [operand_expression...]

As duas opções controlam como o findcomando deve tratar links simbólicos. O comportamento padrão é nunca seguir links simbólicos. O sinalizador -L fará com que o findcomando siga links simbólicos. O sinalizador -H seguirá apenas links simbólicos durante o processamento dos argumentos da linha de comando. Esses sinalizadores são especificados no padrão POSIX para find. Uma extensão comum é o sinalizador -P, para desabilitar explicitamente o seguinte link simbólico.

Pelo menos um caminho deve preceder a expressão. findé capaz de interpretar curingas internamente e os comandos devem ser citados com cuidado para controlar o globbing do shell .

Os elementos de expressão são separados pelo limite do argumento da linha de comando , geralmente representado como um espaço em branco na sintaxe do shell. Eles são avaliados da esquerda para a direita. Eles podem conter elementos lógicos como AND (-and ou -a) e OR (-ou -o), bem como predicados (filtros e ações).

GNU findtem um grande número de recursos adicionais não especificados pelo POSIX.

Predicados

As primárias comumente usadas incluem:

  • -name pattern - testa se o nome do arquivo corresponde ao padrão shell-glob fornecido.
  • -type type - testa se o arquivo é de um determinado tipo. Os tipos de arquivo Unix aceitos incluem:
  • -print - sempre retorna verdadeiro; imprime o nome do arquivo atual mais uma nova linha para o stdout .
  • -print0 - sempre retorna verdadeiro; imprime o nome do arquivo atual mais um caractere nulo para o stdout . Não exigido pelo POSIX.
  • -exec program [argumento ...]; - sempre retorna verdadeiro; execute um programa com os argumentos fixos fornecidos e o caminho atual do arquivo.
  • -exec program [argumento ...] {} + - sempre retorna verdadeiro; execute um programa com os argumentos fixos fornecidos e tantos caminhos quanto possível (até o tamanho máximo da linha de comando, como xargs ). Para a maioria das implementações, ocorrências adicionais de {} significam cópias adicionais do nome dado (recurso não exigido pelo POSIX).
  • -ok programa [argumento ...]; - como -exec , mas retorna verdadeiro ou falso dependendo se o programa retorna 0.

Se a expressão não usar nenhum de -print0 , -print , -exec ou -ok , encontre os padrões para executar -print se as condições forem testadas como verdadeiras.

Operadores

Os operadores podem ser usados ​​para aprimorar as expressões do comando find. Os operadores são listados em ordem decrescente de precedência:

  • (expr) - força a precedência;
  • ! expr - verdadeiro se expr for falso;
  • expr1 expr2 (ou expr1 -a expr2 ) - AND. expr2 não é avaliado se expr1 for falso;
  • expr1 -o expr2 - OU. expr2 não é avaliado se expr1 for verdadeiro.
$ find . -name 'fileA_*' -o -name 'fileB_*'

Este comando procura na árvore de diretório de trabalho atual os arquivos cujos nomes começam com "fileA_" ou "fileB_". Citamos o fileA_*para que o shell não o expanda.

$ find . -name 'foo.cpp' '!' -path '.svn'

Este comando pesquisa a árvore de diretório de trabalho atual, exceto a árvore de subdiretório ".svn" para arquivos cujo nome é "foo.cpp". Citamos o de !modo que não seja interpretado pelo shell como o caractere de substituição de histórico.

Proteção POSIX de saída infinita

Sistemas de arquivos do mundo real, muitas vezes contêm estruturas em loop criadas através do uso de rígidos ou soft links . O padrão POSIX requer que

O findutilitário deve detectar loops infinitos; ou seja, inserir um diretório visitado anteriormente que é um ancestral do último arquivo encontrado. Ao detectar um loop infinito, finddeve escrever uma mensagem de diagnóstico para o erro padrão e deve recuperar sua posição na hierarquia ou encerrar.

Exemplos

Do diretório de trabalho atual

$ find . -name 'my*'

Isso procura na árvore de diretório de trabalho atual os arquivos cujos nomes começam com my . As aspas simples evitam a expansão do shell - sem elas, o shell substituiria my * pela lista de arquivos cujos nomes começam com my no diretório de trabalho atual. Em versões mais recentes do programa, o diretório pode ser omitido e implicará no diretório de trabalho atual.

Arquivos normais apenas

$ find . -name 'my*' -type f

Isso limita os resultados da pesquisa acima a apenas arquivos regulares, excluindo diretórios, arquivos especiais, links simbólicos, etc. my * é colocado entre aspas simples (apóstrofos), caso contrário, o shell o substituiria pela lista de arquivos no atual diretório de trabalho começando com meu ...

Comandos

Os exemplos anteriores criaram listas de resultados porque, por padrão, findexecuta a -printação. (Observe que as versões anteriores do findcomando não tinham nenhuma ação padrão; portanto, a lista de arquivos resultante seria descartada, para perplexidade dos usuários.)

$ find . -name 'my*' -type f -ls

Isso imprime informações estendidas do arquivo.

Pesquisar todos os diretórios

$ find / -name myfile -type f -print

Isso procura em cada diretório por um arquivo normal cujo nome é myfile e o imprime na tela. Geralmente, não é uma boa ideia procurar arquivos dessa maneira. Isso pode levar um tempo considerável, portanto, é melhor especificar o diretório com mais precisão. Alguns sistemas operacionais podem montar sistemas de arquivos dinâmicos que não são compatíveis com o find. Nomes de arquivos mais complexos, incluindo caracteres especiais para o shell, podem precisar ser colocados entre aspas simples.

Pesquisar todos, exceto uma árvore de subdiretórios

$ find / -path excluded_path -prune -o -type f -name myfile -print

Isso procura em todos os diretórios, exceto na árvore de subdiretórios excluída_path (caminho completo incluindo o / à esquerda) que é removido pela -pruneação, para um arquivo regular cujo nome é meuarquivo .

Especifique um diretório

$ find /home/weedly -name myfile -type f -print

Isso procura na árvore de diretórios / home / weedly por arquivos regulares chamados myfile . Você sempre deve especificar o diretório no nível mais profundo que puder lembrar.

Pesquise vários diretórios

$ find local /tmp -name mydir -type d -print

Isso pesquisa a árvore de subdiretórios local do diretório de trabalho atual e a árvore de diretório / tmp para os diretórios chamados mydir .

Ignorar erros

Se você estiver fazendo isso como um usuário diferente de root, pode ignorar os erros de permissão negada (e quaisquer outros). Como os erros são impressos em stderr , eles podem ser suprimidos redirecionando a saída para / dev / null. O exemplo a seguir mostra como fazer isso no shell bash:

$ find / -name myfile -type f -print 2> /dev/null

Se você for um usuário csh ou tcsh , você não pode redirecionar stderr sem redirecionar stdout também. Você pode usar sh para executar o findcomando para contornar isso:

$ sh -c "find / -name myfile -type f -print 2> /dev/null"

Um método alternativo ao usar csh ou tcsh é canalizar a saída de stdout e stderr em um comando grep . Este exemplo mostra como suprimir linhas que contêm erros de permissão negada.

$ find . -name myfile |& grep -v 'Permission denied'

Encontre qualquer um dos arquivos com nomes diferentes

$ find . \( -name '*jsp' -o -name '*java' \) -type f -ls

O -lsoperador imprime informações estendidas e o exemplo encontra qualquer arquivo regular cujo nome termina com 'jsp' ou 'java'. Observe que os parênteses são obrigatórios. Em muitos shells, os parênteses devem ser escapados com uma barra invertida ( \(e \)) para evitar que sejam interpretados como caracteres especiais de shell. O -lsoperador não está disponível em todas as versões do find.

Execute uma ação

$ find /var/ftp/mp3 -name '*.mp3' -type f -exec chmod 644 {} \;

Este comando altera as permissões de todos os arquivos regulares cujos nomes terminam com .mp3 na árvore de diretórios / var / ftp / mp3 . A ação é realizada especificando a instrução no comando. Para cada arquivo regular cujo nome termina com , o comando é executado substituindo pelo nome do arquivo. O ponto-e-vírgula (barra invertida para evitar que o shell o interprete como um separador de comando) indica o fim do comando. A permissão , geralmente mostrada como , concede ao proprietário do arquivo permissão total para ler e gravar o arquivo, enquanto outros usuários têm acesso somente leitura. Em alguns shells, o deve ser citado. O " " final é normalmente citado com um " " inicial, mas também pode ser colocado entre aspas simples. -exec chmod 644 {} \;.mp3chmod 644 {}{}644rw-r--r--{};\

Observe que o comando em si não deve ser colocado entre aspas; caso contrário, você receberá mensagens de erro como

find: echo "mv ./3bfn rel071204": No such file or directory

o que significa que findestá tentando executar um arquivo chamado ' ' e falhando. echo "mv ./3bfn rel071204"

Se você estiver executando sobre muitos resultados, é mais eficiente usar uma variante do exec primário que coleta nomes de arquivos até ARG_MAX e, em seguida, executa COMMAND com uma lista de nomes de arquivos.

$ find . -exec COMMAND {} +

Isso garantirá que os nomes de arquivos com espaços em branco sejam passados ​​para o executado COMMANDsem serem divididos pelo shell.

Excluir arquivos e diretórios

A -deleteação é uma extensão GNU e, ao usá-la, é ativada -depth. Portanto, se você estiver testando um comando find com em -printvez de -deletepara descobrir o que acontecerá antes de aplicá-lo, você precisa usar -depth -print.

Exclua arquivos vazios e imprima os nomes (observe que -emptyé uma extensão exclusiva do fornecedor do GNU findque pode não estar disponível em todas as findimplementações):

$ find . -empty -delete -print

Exclua arquivos normais vazios:

$ find . -type f -empty -delete

Exclua diretórios vazios:

$ find . -type d -empty -delete

Exclua arquivos vazios com o nome 'ruim':

$ find . -name bad -empty -delete

Aviso. - A -deleteação deve ser usada com condições como -emptyou -name:

$ find . -delete # this deletes all in .

Procure por uma string

Este comando pesquisará todos os arquivos da árvore de diretórios / tmp por uma string:

$ find /tmp -type f -exec grep 'search string' /dev/null '{}' \+

O /dev/nullargumento é usado para mostrar o nome do arquivo antes do texto encontrado. Sem ele, apenas o texto encontrado é impresso. (Como alternativa, algumas versões de grep suportam um sinalizador -H que força a impressão do nome do arquivo.) GNU greppode ser usado sozinho para realizar esta tarefa:

$ grep -r 'search string' /tmp

Exemplo de pesquisa por "LOG" na árvore do diretório inicial de jsmith:

$ find ~jsmith -exec grep LOG '{}' /dev/null \; -print
/home/jsmith/scripts/errpt.sh:cp $LOG $FIXEDLOGNAME
/home/jsmith/scripts/errpt.sh:cat $LOG
/home/jsmith/scripts/title:USER=$LOGNAME

Exemplo de pesquisa para a string "ERROR" em todos os arquivos XML na árvore de diretório de trabalho atual:

$ find . -name "*.xml" -exec grep "ERROR" /dev/null '{}' \+

As aspas duplas ("") ao redor da string de pesquisa e aspas simples ('') ao redor das chaves são opcionais neste exemplo, mas necessárias para permitir espaços e alguns outros caracteres especiais na string. Observe que com texto mais complexo (notavelmente em shells mais populares descendentes de `sh` e` csh`) aspas simples são frequentemente a escolha mais fácil, uma vez que as aspas duplas não impedem todas as interpretações especiais . Citar nomes de arquivos com contrações em inglês demonstra como isso pode ficar um tanto complicado, já que uma string com um apóstrofo é mais fácil de proteger com aspas duplas:

$ find . -name "file-containing-can't" -exec grep "can't" '{}' \; -print

Pesquise todos os arquivos pertencentes a um usuário

$ find . -user <userid>

Pesquisa no modo não sensível a maiúsculas e minúsculas

Observe que -inamenão está no padrão e pode não ser compatível com todas as implementações.

$ find . -iname 'MyFile*'

Se a -inameopção não for compatível com seu sistema, técnicas de solução podem ser possíveis, como:

$ find . -name '[mM][yY][fF][iI][lL][eE]*'

Isso usa Perl para construir o comando acima para você (embora em geral esse tipo de uso seja perigoso, uma vez que os caracteres especiais não são devidamente citados antes de serem alimentados na entrada padrão de `sh`):

$ echo 'MyFile*' | perl -pe 's/([a-zA-Z])/[\L\1\U\1]/g;s/(.*)/find . -name \1/' | sh

Pesquisar arquivos por tamanho

Pesquisando arquivos com tamanho entre 100 kilobytes e 500 kilobytes:

$ find . -size +100k -a -size -500k

Pesquisando arquivos vazios:

$ find . -size 0k

Pesquisando arquivos não vazios:

$ find . ! -size 0k

Pesquise arquivos por nome e tamanho

$ find /usr/src ! \( -name '*,v' -o -name '.*,v' \) '{}' \; -print

Este comando pesquisará a árvore de diretórios / usr / src. Todos os arquivos nos formatos '*, v' e '. *, V' são excluídos. Argumentos importantes a serem observados estão na dica de ferramenta exibida ao passar o mouse.

for file in `find /opt \( -name error_log -o -name 'access_log' -o -name 'ssl_engine_log' -o -name 'rewrite_log' -o
 -name 'catalina.out' \) -size +300000k -a -size -5000000k`; do 
 cat /dev/null > $file
done

As unidades devem ser uma de [bckw], 'b' significa blocos de 512 bytes, 'c' significa byte, 'k' significa kilobytes e 'w' significa palavras de 2 bytes. O tamanho não conta blocos indiretos, mas conta blocos em arquivos esparsos que não estão realmente alocados.

Pesquisando arquivos por tempo

  • mtime = hora de modificação
  • ctime = tempo de mudança de inode
  • atime = tempo de acesso

Arquivos modificados um número relativo de dias atrás:

  • + [número] = Pelo menos isso muitos dias atrás.
  • - [número] = Menos de tantos dias atrás.
  • [número] = Exatamente isso há muitos dias.
  • Opcionalmente, adicione -daystartpara medir o tempo desde o início de um dia (0 horas) em vez das últimas 24 horas.

Exemplo para encontrar todos os arquivos de texto na pasta de documentos modificados desde uma semana (ou seja, 7 dias):

find ~/Documents/ -iname "*.txt" -mtime -7

Arquivos modificados antes ou depois de uma data e hora absolutas:

  • -newermt YYYY-MM-DD: Última modificação após a data
  • -not -newermt YYYY-MM-DD: Última modificação antes da data

Exemplo para localizar todos os arquivos de texto editados pela última vez em fevereiro de 2017:

find ~/Documents/ -iname "*.txt"  -newerct 2017-02-01 -not -newerct 2017-03-01
  • -newer [file]: Modificado mais recentemente do que o arquivo especificado.
    • -cnewer: Mesmo com o tempo de mudança do inode.
    • -anewer: Mesmo com o tempo de acesso.
    • Também prefixável com -notpara resultados ou intervalo inversos.

Liste todos os arquivos de texto editados mais recentemente do que "document.txt":

find ~/Documents/ -iname "*.txt"  -newer document.txt

Utilitários relacionados

  • locateé uma ferramenta de pesquisa Unix que pesquisa um banco de dados pré-construído de arquivos em vez de árvores de diretório de um sistema de arquivos. Isso é mais rápido, findmas menos preciso, porque o banco de dados pode não estar atualizado.
  • grepé um utilitário de linha de comando para pesquisar conjuntos de dados de texto simples para linhas que correspondem a uma expressão regular e, por padrão, relatar linhas correspondentes na saída padrão .
  • tree é um utilitário de linha de comando que lista recursivamente arquivos encontrados em uma árvore de diretórios, recuando os nomes de arquivos de acordo com sua posição na hierarquia de arquivos.
  • GNU Find Utilities (também conhecido como findutils) é um pacote GNU que contém implementações das ferramentas finde xargs.
  • BusyBox é um utilitário que fornece várias ferramentas Unix simplificadas em um único arquivo executável, destinado a sistemas operacionais embarcados com recursos muito limitados. Ele também fornece uma versão do find.
  • dir tem a opção / s que pesquisa recursivamente por arquivos ou diretórios.
  • O Plan 9 da Bell Labs usa dois utilitários para substituir find: um walkque apenas percorre a árvore e imprime os nomes e um sorque apenas filtra (como grep) avaliando expressões na forma de um script de shell. Filtros arbitrários podem ser usados ​​por meio de tubos. Os comandos não fazem parte do Plan 9 do User Space , então Benjamin Barenblat do Google tem uma versão portada para sistemas POSIX disponível através do GitHub.
  • fdé uma alternativa simples para findescrita na linguagem de programação Rust .

Veja também

Referências

links externos