Não tenho certeza:
grep -r -i 'the brown dog' /*
é realmente o que você quis dizer. Isso significaria grep recursivamente em todos os arquivos e diretórios não ocultos /
(mas ainda assim procure dentro de arquivos e diretórios ocultos).
Supondo que você quis dizer:
grep -r -i 'the brown dog' /
Algumas coisas a serem observadas:
- Nem todas as
grep
implementações suportam -r
. E entre os que o fazem, os comportamentos diferem: alguns seguem links simbólicos para diretórios ao percorrer a árvore de diretórios (o que significa que você pode acabar procurando várias vezes no mesmo arquivo ou mesmo executar em loops infinitos), outros não. Alguns irão procurar dentro de arquivos de dispositivos (e isso levará algum tempo, /dev/zero
por exemplo) ou tubos ou arquivos binários ..., outros não.
- É eficiente quando
grep
começa a procurar dentro de arquivos assim que os descobre. Mas enquanto ele aparece em um arquivo, não está mais procurando mais arquivos para pesquisar (o que provavelmente é tão bom na maioria dos casos)
Seu:
find / -type f -exec grep -i 'the brown dog' {} \;
(removido o -r
que não fazia sentido aqui) é terrivelmente ineficiente porque você está executando um grep
por arquivo. ;
deve ser usado apenas para comandos que aceitam apenas um argumento. Além disso, aqui, como grep
parece apenas em um arquivo, ele não imprimirá o nome do arquivo, portanto você não saberá onde estão as correspondências.
Você não está olhando dentro de arquivos de dispositivos, canais, links simbólicos ..., não está seguindo links simbólicos, mas ainda está potencialmente olhando dentro de coisas como /proc/mem
.
find / -type f -exec grep -i 'the brown dog' {} +
seria muito melhor porque o grep
menor número possível de comandos seria executado. Você obteria o nome do arquivo, a menos que a última execução tenha apenas um arquivo. Para isso, é melhor usar:
find / -type f -exec grep -i 'the brown dog' /dev/null {} +
ou com GNU grep
:
find / -type f -exec grep -Hi 'the brown dog' {} +
Observe que grep
não será iniciado até find
encontrar arquivos suficientes para mastigar, portanto haverá um atraso inicial. E find
não continuará pesquisando por mais arquivos até que o anterior grep
retorne. Alocar e passar a grande lista de arquivos tem algum impacto (provavelmente desprezível); portanto, em geral, será menos eficiente do que um grep -r
que não segue o link simbólico ou olha para os dispositivos.
Com as ferramentas GNU:
find / -type f -print0 | xargs -r0 grep -Hi 'the brown dog'
Como acima, o menor número grep
possível de instâncias será executado, mas find
continuará procurando por mais arquivos enquanto a primeira grep
chamada estiver dentro do primeiro lote. Isso pode ou não ser uma vantagem. Por exemplo, com os dados armazenados em discos rígidos rotacionais find
e o grep
acesso a dados armazenados em diferentes locais do disco, a velocidade do disco diminuirá a velocidade, fazendo com que a cabeça do disco se mova constantemente. Em uma configuração de RAID (onde find
e grep
pode acessar discos diferentes) ou em SSDs, isso pode fazer uma diferença positiva.
Em uma configuração de RAID, a execução de várias chamadas simultâneas grep
também pode melhorar as coisas. Ainda com as ferramentas GNU no armazenamento RAID1 com 3 discos,
find / -type f -print0 | xargs -r0 -P2 grep -Hi 'the brown dog'
pode aumentar significativamente o desempenho. Observe, no entanto, que o segundo grep
será iniciado apenas quando forem encontrados arquivos suficientes para preencher o primeiro grep
comando. Você pode adicionar uma -n
opção xargs
para que isso aconteça mais cedo (e passar menos arquivos por grep
chamada).
Observe também que, se você estiver redirecionando a xargs
saída para algo que não seja um dispositivo terminal, os greps
s começarão a armazenar buffer em sua saída, o que significa que a saída desses grep
s provavelmente será intercalada incorretamente. Você precisaria usar stdbuf -oL
(quando disponível, como no GNU ou FreeBSD) neles para solucionar isso (você ainda pode ter problemas com linhas muito longas (normalmente> 4KiB)) ou cada um deles escrever sua saída em um arquivo separado e concatená-los tudo no final.
Aqui, a string que você está procurando é fixa (não uma regexp), portanto, o uso da -F
opção pode fazer a diferença (improvável, pois as grep
implementações já sabem como otimizar isso).
Outra coisa que pode fazer uma grande diferença é fixar o código do idioma em C se você estiver em um código de idioma de vários bytes:
find / -type f -print0 | LC_ALL=C xargs -r0 -P2 grep -Hi 'the brown dog'
Para evitar olhar para dentro /proc
, /sys
..., use -xdev
e especifique os sistemas de arquivos nos quais deseja pesquisar:
LC_ALL=C find / /home -xdev -type f -exec grep -i 'the brown dog' /dev/null {} +
Ou remova os caminhos que você deseja excluir explicitamente:
LC_ALL=C find / \( -path /dev -o -path /proc -o -path /sys \) -prune -o \
-type f -exec grep -i 'the brown dog' /dev/null {} +