Maneira eficiente de pesquisar strings no arquivo find e grep

4

Estou pesquisando todos os arquivos que contêm uma string específica em um arquivador (em uma antiga estação de trabalho HP-UX).

Eu não sei onde os arquivos estão localizados no sistema de arquivos (existem muitos diretórios, com um grande número de scripts, arquivos de texto simples e binários).

Preciso que a opção grep -R não exista neste sistema; então estou usando o find e o grep para recuperar quais arquivos contêm minha string:

find . -type f -exec grep -i "mystring" {} \;

Não estou satisfeito com este comando: ele é muito lento e não imprime o nome e o caminho do arquivo no qual o grep correspondeu à minha string. Além disso, se houver um erro, ele será ecoado na saída do meu console.

Então, achei que poderia fazer melhor:

find . -type f -exec grep -l -i "mystring" {} 2>/dev/null \;

Mas é muito lento.

Você tem uma alternativa mais eficiente para esse comando?

Obrigado.

    
por zeropouet 19.06.2013 / 17:45

2 respostas

2

O mais rápido que posso criar é usar xargs para compartilhar a carga:

find . -type f -print0  | xargs -0 grep -Fil "mypattern" 

Executando alguns benchmarks em um diretório contendo 3631 arquivos:

$ time find . -type f -exec grep -l -i "mystring" {} 2>/dev/null \;

real    0m15.012s
user    0m4.876s
sys     0m1.876s

$ time find . -type f -exec grep -Fli "mystring" {} 2>/dev/null \;

real    0m13.982s
user    0m4.328s
sys     0m1.592s


$ time find . -type f -print0  | xargs -0 grep -Fil "mystring" >/dev/null 

real    0m3.565s
user    0m3.508s
sys     0m0.052s

Suas outras opções seriam simplificar limitando a lista de arquivos usando find :

   -executable
          Matches files which are executable and  direc‐
          tories  which  are  searchable (in a file name
          resolution sense).  
   -writable
          Matches files which are writable.             

   -mtime n
          File's  data was last modified n*24 hours ago.
          See the comments for -atime to understand  how
          rounding  affects  the  interpretation of file
          modification times.
   -group gname
          File  belongs to group gname (numeric group ID
          allowed).
   -perm /mode
          Any  of  the  permission bits mode are set for
          the file.  Symbolic modes are accepted in this
          form.  You must specify 'u', 'g' or 'o' if you
          use a symbolic mode. 
   -size n[cwbkMG]  <-- you can set a minimum or maximum size
          File uses n units  of  space.  

Ou alterando grep :

Você já está usando a opção grep -l , que faz com que o nome do arquivo seja impresso e, mais importante, pare na primeira correspondência:

   -l, --files-with-matches
       Suppress normal output; instead print the name of each input file  from
       which  output would normally have been printed.  The scanning will stop
       on the first match.  (-l is specified by POSIX.)

A única outra coisa em que posso pensar para acelerar as coisas seria garantir que seu padrão não seja interpretado como um regex (como sugerido pelo @suspectus) usando a opção -F .

    
por 19.06.2013 / 18:05
1

Use grep -F , que diz grep para interpretar o padrão como uma string e não como uma expressão regular (que eu suponho que você não precisa). Pode ser apreciavelmente mais rápido que grep - dependendo do tamanho dos arquivos que estão sendo analisados.

No Ubuntu e no RHEL Linux, a opção -H mostrará o caminho do arquivo de um arquivo correspondente.

find . -type f -exec grep -FHi "mystring" {} +
    
por 19.06.2013 / 18:20