Não tenho certeza:
grep -r -i 'the brown dog' /*
é realmente o que você quis dizer. Isso significaria grep recursivamente em todos os arquivos não ocultos e dirs em /
(mas ainda olhe dentro dos arquivos ocultos e dirs dentro deles).
Supondo que você quis dizer:
grep -r -i 'the brown dog' /
Algumas coisas a serem observadas:
- Nem todas as implementações
grep
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 até executar em loops infinitos), outros não. Alguns vão olhar dentro dos arquivos do dispositivo (e vai demorar algum tempo em/dev/zero
, por exemplo) ou canos ou arquivos binários ..., outros não. - É eficiente porque
grep
começa a procurar dentro dos arquivos assim que os descobre. Mas, enquanto olha em um arquivo, ele não está mais procurando por mais arquivos para pesquisar (o que provavelmente é melhor que na maioria dos casos)
Seu:
find / -type f -exec grep -i 'the brown dog' {} \;
(removeu o -r
que não fazia sentido aqui) é terrivelmente ineficiente porque você está executando um grep
por arquivo. ;
só deve ser usado para comandos que aceitam apenas um argumento. Além disso, aqui, porque 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á procurando dentro de arquivos de dispositivos, canais, links simbólicos ..., você não está seguindo links simbólicos, mas ainda está potencialmente procurando por coisas como /proc/mem
.
find / -type f -exec grep -i 'the brown dog' {} +
seria muito melhor porque seriam executados o mínimo de grep
de comandos possíveis. Você obteria o nome do arquivo, a menos que a última execução tivesse apenas um arquivo. Para isso, é melhor usar:
find / -type f -exec grep -i 'the brown dog' /dev/null {} +
ou com o GNU grep
:
find / -type f -exec grep -Hi 'the brown dog' {} +
Observe que grep
não será iniciado até que find
encontre arquivos suficientes para serem mastigados, portanto haverá algum atraso inicial. E find
não continuará procurando mais arquivos até que o grep
anterior tenha retornado. Alocar e passar a lista de arquivos grandes tem algum (provavelmente insignificante) impacto, então, no geral, provavelmente será menos eficiente do que um grep -r
que não segue o symlink ou olha dentro de dispositivos.
Com ferramentas GNU:
find / -type f -print0 | xargs -r0 grep -Hi 'the brown dog'
Como acima, o mínimo possível de grep
instâncias será executado, mas find
continuará procurando por mais arquivos enquanto a primeira grep
invocação estiver procurando dentro do primeiro lote. Isso pode ou não ser uma vantagem. Por exemplo, com dados armazenados em discos rígidos rotativos, find
e grep
acessando dados armazenados em locais diferentes no disco diminuirão a taxa de transferência do disco fazendo com que a cabeça do disco se mova constantemente. Em uma configuração de RAID (onde find
e grep
podem 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 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. No entanto, observe que o segundo grep
só será iniciado quando forem encontrados arquivos suficientes para preencher o primeiro comando grep
. Você pode adicionar uma opção -n
a xargs
para que isso aconteça mais cedo (e passar menos arquivos por grep
invocação).
Observe também que, se você estiver redirecionando a saída xargs
para qualquer coisa que não seja um dispositivo terminal, o greps
s começará a armazenar em buffer sua saída, o que significa que a saída desses grep
s provavelmente será intercalada incorretamente. Você teria que usar stdbuf -oL
(onde disponível como no GNU ou FreeBSD) para contornar isso (você ainda pode ter problemas com linhas muito longas (geralmente > 4KiB)) ou ter cada um escrevendo sua saída em um separado arquivar e concatenar todos eles no final.
Aqui, a string que você está procurando é fixa (não um regexp), portanto, usar a opção -F
pode fazer a diferença (improvável, pois grep
implementations sabem como otimizar isso já).
Outra coisa que poderia fazer uma grande diferença é corrigir o código do idioma para 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 de /proc
, /sys
..., use -xdev
e especifique os sistemas de arquivos nos quais você deseja pesquisar:
LC_ALL=C find / /home -xdev -type f -exec grep -i 'the brown dog' /dev/null {} +
Ou limpe 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 {} +