grep
é de E / S, o que significa que sua velocidade é dominada pela velocidade com que consegue ler os arquivos que está pesquisando. Múltiplas pesquisas em paralelo podem competir umas com as outras pela E / S do disco, então você pode não ver muita aceleração.
Se você precisar apenas de nomes de arquivos correspondentes e não das correspondências encontradas nos arquivos, você deverá executar grep com o -l
flag. Esse sinalizador faz com que o grep apenas imprima nomes de arquivos correspondentes e não imprima as linhas correspondentes. O valor aqui é que ele permite que o grep pare de pesquisar um arquivo depois de encontrar uma correspondência, para que possa reduzir a quantidade de trabalho que o grep precisa fazer.
Se você estiver pesquisando strings fixas em vez de expressões regulares, tente usar fgrep
em vez de grep
. O Fgrep é uma variante do grep que procura por strings fixas, e procurar por strings fixas é mais rápido do que executar uma pesquisa de expressões regulares. Você pode ou não ver qualquer melhoria disso, porque as versões modernas do grep são provavelmente inteligentes o suficiente para otimizar pesquisas de cadeias fixas de qualquer maneira.
Se você quiser tentar executar várias pesquisas em paralelo, poderá fazê-lo usando utilitários de shell. Uma maneira seria criar uma lista de nomes de arquivos, dividi-la em partes e executar o grep separadamente para cada lista:
find /path/to/files -type f -print | split -l 10000000 list.
for file in list.*; do
grep -f ${file} -l 'some text' > ${file}.out &
done
wait
cat $*.out > filepaths.log
rm list.*
Isso usa find
para localizar os arquivos, divide a lista de nomes de arquivos em grupos de dez milhões e executa grep em paralelo para cada grupo. A saída dos greps está reunida no final. Isso deve funcionar para arquivos com nomes típicos, mas falharia em arquivos que tinham novas linhas em seus nomes, por exemplo.
Outra abordagem usa xargs. Primeiro, você teria que escrever um script de shell simples que executa grep em segundo plano:
#!/bin/bash
grep -l 'search text' "$@" >> grep.$$.out &
Isso executará o grep na lista de arquivos especificados como argumentos para o script, gravando o resultado em um arquivo com o nome do PID do processo. O processo grep é executado em segundo plano.
Então você executaria o script assim:
find /path/to/files -type f -print0 | xargs -0 -r /my/grep/script
[ wait for those to finish ]
cat grep.*.out > filepaths.log
rm grep.*.out
Nesse caso, xargs
agrupará os nomes de arquivos em grupos e executará o script uma vez para cada grupo. O script executará uma instância do grep uma vez para cada grupo. Depois que todas as instâncias do grep terminarem, você poderá combinar suas saídas. Infelizmente, não consegui pensar em uma maneira inteligente de esperar automaticamente que as instâncias do grep terminem aqui, então talvez seja necessário fazer isso manualmente.