Preciso localizar .php
e .pl
arquivos que não contenham uma string (por exemplo aaa
), mas contenham outra (por exemplo bbb
).
Atualmente estou usando este comando:
find /path/ \( -iname '*.php*' -or -name '*.pl*' \) -exec sh -c 'grep -l -v "aaa" {} | grep -l "bbb" {}' \; > resulttofile
É cerca de meio milhão de arquivos para pesquisar, então estou pensando,
- Se meu comando funcionar corretamente - algumas amostras de olho dão resultado positivo,
- Se for possível tornar-se mais rápido (atualmente leva cerca de 2 minutos em uma VM, mas mais arquivos serão adicionados) usando algum outro formulário, ou
awk
emsed
vez degrep
- ou talvez apenas um combinadogrep
em vez de dois.
O sistema é um Debian GNU/Linux.
Seu comando não funciona corretamente: o primeiro
grep
listará qualquer arquivo que contenha uma linha que não corresponda"aaa"
e o segundogrep
ignorará a saída do primeiro, pois recebeu seu próprio arquivo para processar - então você obterá uma lista de arquivos correspondentes"bbb"
, independentemente se contêm"aaa"
ou não. Você precisaria pedirgrep
para listar apenas um arquivo se ele não contiver nenhuma correspondência de linha"aaa"
(grep -L
), e usarxargs
para processar a lista de arquivos resultante e apenas alimentá-la para o segundogrep
(ou tornar o segundogrep
condicional no resultado do primeiro).Além disso, funcionaria apenas enquanto os nomes dos arquivos
find
listados não causassem problemas para o shell - notavelmente, incluir{}
diretamente no comando dado significash -c
que os nomes dos arquivos podem acabar sendo interpretados como comandos do shell (consulte É possível usar `find -exec sh -c` com segurança ?O seguinte exigirá menos
grep
invocações e é mais seguro, supondo que você esteja usando GNUgrep
:O
-or
operador é uma extensão GNU parafind
. Use-o
para portabilidade.Não testado, mas isso deve fazer o que eu acho que você quer, usando GNU awk para
nextfile
eENDFILE
O acima chama o awk apenas uma vez em vários arquivos por vez, portanto, deve ser eficiente.
O acima é como geralmente combinar vários padrões em um arquivo e, em seguida, avaliar os resultados da combinação de correspondências assim que o arquivo for totalmente lido, mas como @G-Man diz 'Reinstaurar Monica' mencionado em um comentário, você pode torná-lo mais eficiente neste caso específico, parando de ler o arquivo atual se/quando
aaa
corresponder, pois o critério de sucesso éaaa
não estar presente:Você pode encadear várias diretivas -exec (ou outras) com um comando find:
(A quebra de linha é apenas para caber no layout do SE).