Quando quero pesquisar em toda uma árvore algum conteúdo, uso
find . -type f -print0 | xargs -0 grep <search_string>
Existe uma maneira melhor de fazer isso em termos de desempenho ou brevidade?
Quando quero pesquisar em toda uma árvore algum conteúdo, uso
find . -type f -print0 | xargs -0 grep <search_string>
Existe uma maneira melhor de fazer isso em termos de desempenho ou brevidade?
Respostas:
Verifique se a sua opção de grep
suporte -r
(para recursão ):
grep -r <search_string> .
--exclude-dir
para abordar o desempenho e temos um vencedor!
grep
nas recentes distribuições do FreeBSD e Linux o suportam. E por que --exclude-dir
? Você não pediu para procurar uma árvore inteira ?
--exclude-dir
é realmente útil no meu caso de uso (porque partes da subárvore são grandes, mas inúteis) e perguntei sobre desempenho ... mas você está certo, não é necessário.
--exclude-dir
é exclusivo do GNU grep
. (-:
Uma resposta subótima: em vez de canalizar a saída para find
into grep
, você pode simplesmente executar
find . -type f -exec grep 'research' {} '+'
e voila, um comando em vez de dois!
explicação:
find . -type f
encontre todos os arquivos regulares dentro.
-exec grep 'research'
grep 'pesquisa'
{}
no nome do arquivo encontrado
'+'
use um comando por todos os nomes de arquivos, não uma vez por nome de arquivo.
Nota: com ';'
isso teria sido uma vez por nome de arquivo.
Fora isso, se você usar isso para processar o código-fonte, poderá pesquisar o ack
que é feito para procurar bits de código facilmente.
Editar:
Você pode estender um pouco essa pesquisa. Primeiro, você pode usar a -name ''
opção de find
para procurar arquivos com padrão de nomeação específico.
Por exemplo :
somente arquivos que correspondem aos logs: -name '*.log'
apenas arquivos que correspondem aos cabeçalhos c, mas você não pode usar letras maiúsculas ou minúsculas nas extensões do seu nome de arquivo: -iname *.c
Nota: como para grep
e ack
, a -i
opção significa insensível a maiúsculas e minúsculas neste caso.
Nesse caso, o grep será exibido sem cor e sem números de linha.
Você pode mudar isso com o --color
e os -n
interruptores (números de cor e de linhas em arquivos respectivamente).
No final, você pode ter algo como:
find . -name '*.log' -type f -exec grep --color -n 'pattern' {} '+'
por exemplo
$ find . -name '*.c' -type f -exec grep -n 'hello' {} '+'
./test2/target.c:1:hello
-name '*.log'
é mais rápido.
Se você deseja recursar em subdiretórios:
grep -R 'pattern' .
A -R
opção não é uma opção padrão, mas é suportada pelas grep
implementações mais comuns .
-r
em vez de -R
pular ligações simbólicas ao GNU grep está em questão
grep
implementações atuais do GNU capturem recursões, eu acho. Caso contrário, depende do que você quer dizer com "árvore".
grep
deve fazer. Se o usuário tem laços link simbólico em sua estrutura de diretório, bem, isso é problema do usuário :-)
/sys/devices/cpu/subsystem/devices/cpu/subsystem/devices/cpu/...
(-XI como ferramentas de babá para mim (a menos que elas forneçam magia estranha que chamam de "AI"). (-;
Como observado acima, -r
ou -R
(dependendo do tratamento do link simbólico desejado) é uma opção rápida.
No entanto, -d <action>
pode ser útil às vezes.
O interessante -d
é o comando skip, que silencia o "grep: directory_name: Is a directory" quando você deseja apenas verificar o nível atual.
$ grep foo *
grep: q2: Is a directory
grep: rt: Is a directory
$ grep -d skip foo *
$
e claro:
$ grep -d recurse foo *
(list of results that don't exist because the word foo isn't in our source code
and I wouldn't publish it anyway).
$
A -d skip
opção é REALMENTE útil dentro de outro script para que você não precise 2> /dev/null
. :)
Se você estiver lidando com muitos arquivos, o grep será executado mais rapidamente se você remover os arquivos que eles precisam pesquisar, em vez de grep todos os arquivos em subpastas.
Eu uso esse formato algumas vezes:
grep "primary" `find . | grep cpp$`
Encontre todos os arquivos nas subpastas .
desse fim em cpp
. Em seguida, grep esses arquivos para "primário".
Se desejar, você pode continuar canalizando esses resultados para outras chamadas grep:
grep "primary" `find . | grep cpp$` | grep -v "ignoreThis" | grep -i "caseInsensitiveGrep"