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 grepsuporte -r(para recursão ):
grep -r <search_string> .
--exclude-dirpara abordar o desempenho e temos um vencedor!
grepnas 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 findinto 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 ackque é 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 findpara 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 grepe ack, a -iopçã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 --colore os -ninterruptores (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 -Ropção não é uma opção padrão, mas é suportada pelas grepimplementações mais comuns .
-rem vez de -Rpular ligações simbólicas ao GNU grep está em questão
grepimplementações atuais do GNU capturem recursões, eu acho. Caso contrário, depende do que você quer dizer com "árvore".
grepdeve 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, -rou -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 skipopçã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"