Como procurar por uma string somente em arquivos de texto? (recursivamente)

3

Eu posso listar todos os arquivos de texto (por mimetype) em uma pasta com:

find . -type f -print0 | xargs -0 file -i | fgrep -i text | sed 's/:$//g' 2>/dev/null | awk 'BEGIN {FS=": "} {print $1}'

Ok. Mas como eu posso adicionar "fgrep" para isso, para procurar nesses arquivos por "STRING" (regexp não é necessário, é por isso que o fgrep).

isso não é bom:

fgrep -iR "STRING" *

porque ele começa a procurar em arquivos ISO, arquivos binários também ...

Fedora14 / bash.

    
por LanceBaynes 14.08.2011 / 14:00

2 respostas

10

Primeiro , o grep : você pode dizer para não pesquisar arquivos binários - use a opção -I - como diz a manpage:

-I     Process a binary  file  as  if  it  did  not  contain  matching data;
       this  is  equivalent  to  the --binary-files=without-match option.

Segundo , o find : Para evitar o uso de xargs e muita tubulação, faça uso do teste -exec do programa find . Você pode facilmente criar uma cadeia de testes lógicos usando isto: cada% consecutiva-exec é executado se todos os comandos anteriores retornaram 0 (terminados com sucesso).

    
por 14.08.2011 / 15:04
1

A de @rozcietrzewiacz é uma ótima solução, mas se você ainda quiser ficar com arquivos de texto (conforme retornado por file ), você pode criar cuidadosamente uma matriz de nomes de arquivos e executar seu comando grep nessa array.

Eu suponho o seguinte:

  • em nenhum nome de arquivo existe uma nova linha (mas espaços podem estar presentes);
  • a file util que suporta -0 e -i opções;
  • GNU sed ou um sed que suporta \x códigos de caracteres ex-decimais.

Aqui está um exemplo

#!/bin/bash

get_file_list() {
  local path="$1"
  find "$path" -type f -exec file -0i {} + |
    sed -n '/\x00  *text\//s/\x00.*//p'
}

list=()
while IFS= read -r line; do
  list+=("$line")
done < <(get_file_list .)

# to choose options and pattern
grep -i pattern "${list[@]}"

O comando sed usa uma sequência de linhas de texto proveniente de file , composta de um nome de arquivo, um byte NUL e o tipo mime. Se na segunda parte (depois do NUL) houver a palavra text/ , remova essa parte e apenas imprima o nome do arquivo; caso contrário, não imprima nada.

    
por 14.08.2011 / 15:23

Tags