2012-03-05 23:28:16 +0000 2012-03-05 23:28:16 +0000
148
148

Como ignorar certos nomes de ficheiros usando "find"?

Um dos meus comandos BASH favoritos é:

find . -name '*.*' -exec grep 'SearchString' {} /dev/null \;

que pesquisa o conteúdo de todos os ficheiros no directório actual e abaixo dele para o SearchString especificado. Como programador, isto tem vindo a ser útil por vezes.

Devido ao meu projecto actual, e à estrutura da minha base de códigos, contudo, gostaria de tornar este comando BASH ainda mais avançado, não pesquisando quaisquer ficheiros que estejam dentro ou abaixo de um directório que contenha “.svn”, ou quaisquer ficheiros que terminem com “.html”

A página MAN para encontrar-me um pouco confusa. Tentei usar -prune, e isso deu-me um comportamento estranho. Numa tentativa de saltar apenas as páginas .html (para começar), tentei :

find . -wholename './*.html' -prune -exec grep 'SearchString' {} /dev/null \;

e não consegui o comportamento que esperava. Acho que poderia estar a perder o ponto de -prune. Poderiam ajudar-me?

Obrigado

Respostas (3)

209
209
209
2012-03-06 00:40:37 +0000

Pode usar a funcionalidade de negar (!) para não combinar ficheiros com nomes específicos:

find . ! -name '*.html' ! -path '*.svn*' -exec grep 'SearchString' {} /dev/null \;

Assim, se o nome terminar em .html ou contiver .svn em qualquer parte do caminho, não coincidirá, e por isso o executante não será executado.

12
12
12
2012-03-06 13:54:15 +0000

Tenho o mesmo problema há muito tempo, e existem várias soluções que podem ser aplicáveis em diferentes situações:

  • ack-grep* é uma espécie de “desenvolvedor grep” que por defeito salta os directórios de controlo de versões e ficheiros temporários. A página man explica como pesquisar apenas tipos de ficheiros específicos e como definir os seus próprios . As opções
  • grep próprias --exclude e --exclude-dir podem ser utilizadas muito facilmente para saltar os ficheiros globs e single directórios (sem globbing para directórios, infelizmente).
  • find . \( -type d -name '.svn' -o -type f -name '*.html' \) -prune -o -print0 | xargs -0 grep ... devem funcionar, mas as opções acima mencionadas são provavelmente menos incómodas a longo prazo.
9
9
9
2012-03-06 03:29:21 +0000

O seguinte comando find faz a poda de directórios cujos nomes contém .svn, Embora não desça para o directório, o nome do caminho podado é impresso …(-name '*.svn' é a causa!) …

Pode filtrar os nomes dos directórios através: grep -d skip que silenciosamente ignora tais “nomes de directórios” de entrada.

Com o GNU grep, pode usar -H em vez de /dev/null. Como uma pequena questão lateral: pode ser muito mais rápido que `\;`, por exemplo, para 1 milhão de ficheiros de uma linha, usando `\;` levou _4m20s_, usando levou apenas 1.2s.

O método seguinte utiliza xargs em vez de -exec, e assume que não existem novas linhas \n em nenhum dos seus ficheiros nomes*. Como aqui usado, xargs é muito igual ao `do findxargs`.

'\n' pode passar nomes de ficheiro que contenham espaços consecutivos alterando o delimitador de entrada para -d com a opção .svn.

Isto exclui os directórios cujos nomes contêm .html e greps apenas ficheiros que não terminam com 0x6&.

find . \( -name '*.svn*' -prune -o ! -name '*.html' \) |
   xargs -d '\n' grep -Hd skip 'SearchString'
```.