Um dos meus comandos BASH favoritos é:
find . -name '*.*' -exec grep 'SearchString' {} /dev/null \;
que pesquisa o conteúdo de todos os arquivos no diretório atual e abaixo do diretório SearchString especificado. Como desenvolvedor, isso às vezes é útil.
No entanto, devido ao meu projeto atual e à estrutura da minha base de código, eu gostaria de tornar esse comando BASH ainda mais avançado, não pesquisando arquivos que estejam dentro ou abaixo de um diretório que contenha ".svn" ou quaisquer arquivos que termine com ".html"
A página MAN para encontrar meio que me confundiu. Eu tentei usar -une, e isso me deu um comportamento estranho. Na tentativa de pular apenas as páginas .html (para iniciar), tentei:
find . -wholename './*.html' -prune -exec grep 'SearchString' {} /dev/null \;
e não conseguiu o comportamento que eu esperava. Acho que posso estar perdendo o ponto de podar. Vocês poderiam me ajudar?
obrigado
find
não é um comando bash build-in, mas um programa separadogrep -rl 'SearchString'
find
para pesquisar dentro de um arquivo.-name '*.*'
não encontra todos os arquivos: apenas aqueles com um.
em seu nome (o uso de*.*
geralmente é um DOS-ism, enquanto no Unix, você normalmente usa apenas*
para isso). Para realmente combiná-los todos, basta remover o argumento completamente:find . -exec ...
. Ou se você deseja aplicar apenas grep a arquivos (e pular diretórios), façafind . -type f -exec ...
.Respostas:
Você pode usar o recurso negar (!) De localizar para não corresponder aos arquivos com nomes específicos:
Portanto, se o nome terminar em .html ou contiver .svn em qualquer lugar do caminho, ele não corresponderá e, portanto, o exec não será executado.
fonte
*.*
correspondência era garantir que apenas correspondessem arquivos contendo um.
? Encontrar irá corresponder a todos os arquivos na ausência de umaname
directiva, de modo que o acima irá corresponder a tudo, exceto html e svn-wholename '*.svn*'
mais do que-name
..svn
diretórios sejam excluídos dos resultados da pesquisa.! -name '.'
deve excluir.
dos resultados encontrados.Eu tive 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 "desenvolvedorgrep
" que, por padrão, ignora os diretórios de controle de versão e os arquivos temporários. Aman
página explica como pesquisar apenas tipos de arquivos específicos e como definir seus próprios .grep
As próprias opções--exclude
e--exclude-dir
podem ser usadas com muita facilidade para ignorar os globs de arquivos e os diretórios únicos (infelizmente não há globs nos diretórios).find . \( -type d -name '.svn' -o -type f -name '*.html' \) -prune -o -print0 | xargs -0 grep ...
deve funcionar, mas as opções acima provavelmente são menos problemáticas a longo prazo.fonte
O
find
comando a seguir remove os diretórios cujos nomes contêm.svn
, embora não desça no diretório, o nome do caminho removido é impresso ... (-name '*.svn'
é a causa!) ..Você pode filtrar os nomes dos diretórios via:
grep -d skip
que ignora silenciosamente esses "nomes de diretórios" de entrada.Com o GNU grep, você pode usar em
-H
vez de/dev/null
. Como um pequeno problema:\+
pode ser muito mais rápido do que\;
, por exemplo. para 1 milhão de arquivos de uma linha, o uso\;
levou 4m20s , o uso\+
levou apenas 1,2s .O método a seguir usa em
xargs
vez de-exec
e assume que não há novas linhas\n
em nenhum dos seus nomes de arquivo . Como usado aqui,xargs
é o mesmo que o de encontrar\+
.xargs
pode passar nomes de arquivos que contêm espaços consecutivos alterando o delimitador de entrada para'\n'
com a-d
opçãoIsso exclui diretórios cujos nomes contêm
.svn
e recebem somente arquivos que não terminam.html
.fonte
\+
variante da ação -exec. Viva para pequenas questões secundárias!+
não é um caractere especial para o shell, você não precisa digitar\
antes dele.