Como grep as recursivas 50 primeiras linhas de cada arquivo em um diretório?

10

Eu preciso pesquisar as primeiras 50 linhas de cada arquivo em um diretório e seus subdiretórios.

Isso fará a parte recursiva, mas como limite apenas as 50 primeiras linhas de cada arquivo?

grep -r "matching string here" .

Alguns desses arquivos são enormes e eu só quero que eles correspondam nas 50 primeiras linhas. Estou tentando acelerar o processo, não pesquisando megabytes de dados binários em alguns arquivos.

zevlag
fonte
Deseja apenas conhecer os arquivos correspondentes ou deseja ter apenas a sequência correspondente ou deseja a sequência correspondente junto com o nome do arquivo?
gniourf_gniourf

Respostas:

11
  • Se você deseja apenas os arquivos que correspondem:

    find . -type f -exec bash -c 'grep -q "matching string here" < <(head -n 50 "$1")' _ {} \; -printf '%p\n'
    

    ou

    find . -type f -exec bash -c 'grep -q "matching string here" < <(head -n 50 "$1") && printf '%s\n' "$1"' _ {} \;
    
  • Se você deseja apenas as seqüências correspondentes:

    find . -type f -exec head -n 50 {} \; | grep "matching string here"
    

    ou melhor,

    find . -type f -exec head -q -n 50 {} + | grep "matching string here"
    
  • E se você quer os dois:

    find . -type f -exec bash -c 'mapfile -t a < <(head -n 50 "$1" | grep "matching string here"); printf "$1: %s\n" "${a[@]}"' _ {} \;
    

Observações

  • Poderia ser um pouco mais fácil com em sedvez do combo head- grep.
  • Quero enfatizar que todos os três métodos são 100% seguros em relação aos nomes de arquivos que podem conter símbolos engraçados (espaços, novas linhas etc.).
  • Em dois desses métodos, suponho que você tenha uma versão decentemente recente do bash.
  • Você pode usar -exec ... +em cada método, mas precisará codificar seu loop interno! (exercício trivial deixado para o leitor). Isso pode ser um pouco mais eficiente se você tiver um zilhão de arquivos.
gniourf_gniourf
fonte
4

Se você precisar da saída grep como no original, poderá:

find . -type f | while read f; do 
  if head -n 50 "$f"|grep -s "matching string here"; then
    grep "matching string here" "$f" /dev/null 
  fi
done

Se você precisar apenas dos nomes dos arquivos, poderá substituir o 2º grep echo "$f".

Michael Suelmann
fonte
1

Você precisará combinar alguns utilitários diferentes para obter a funcionalidade desejada. Use o findcomando para recursar os diretórios, encontrar todos os arquivos e executar o headcomando em cada arquivo encontrado. O headcomando pode ser usado para despejar apenas as primeiras 50 linhas de cada arquivo. Por fim, canalize a saída para grep para procurar a string desejada.

find . -type f -exec head -n 50 {} ";" | grep "matching string here"

Cabelo do cachorro
fonte