Compactando padrões de nome 'find'

2

Estou usando

find . -name '*.[cCHh][cC]' -exec grep -nHr "$1" {} ';'
find . -name '*.[cCHh]' -exec grep -nHr "$1" {} ';'

para procurar uma string em todos os arquivos que terminam com .c, .C, .h, .H, .cc e .CC listados em todos os subdiretórios. Mas como isso inclui dois comandos, isso parece ineficiente.

Como escrevo um regex para incluir arquivos .c, .C, .h, .H, .cc e .CC usando um único regex?

EDIT: Estou executando isso no bash em uma máquina Linux.

    
por Arpith 19.10.2012 / 09:38

3 respostas

3

Como você (incorretamente - o que você usou é um padrão de shell) mencionou no assunto, você deve usar expressões regulares:

find . -iregex '.*\.[ch]+'

A abordagem acima é preguiçosa, que também encontrará .ch, .hh e similares, se houver. Para correspondências exatas, você ainda precisa enumerar o que deseja, mas isso ainda é mais fácil com expressões regulares:

find . -regex '.*\.\(c\|C\|cc\|CC\|h\|H\)'
    
por 19.10.2012 / 09:49
1

Portável / padronizado (padrões POSIX, Unix (SUS) e Linux (LSB)) e com eficiência, você o escreveria:

find . \( -name '*.cc' -o -name '*.CC' -o -name '*.[cChH]' \) \
  -type f -exec grep -n -- "$1" /dev/null {} +

O ponto mais importante aqui é usar + em vez de ; . Caso contrário, você executará um comando grep por arquivo.

A opção -H é específica do GNU, mas a adição de /dev/null (garante que grep obtenha pelo menos dois arquivos para verificar) garante que o grep exiba o nome do arquivo.

Você precisará de "-", a menos que possa garantir que $1 nunca comece com - .

Adicionando -type f aqui, para evitar investigar arquivos não-regulares (como diretórios), mas como isso significa que também exclui links simbólicos, você pode deixar isso de lado.

    
por 19.10.2012 / 10:44
1

Pode ser encurtado para esta linha única:

find -type f -regextype posix-egrep -iregex '.*\.(cc|h|c)$' -exec grep -nHr "$1" {} \;

    
por 19.10.2012 / 09:50