Como encontrar arquivos que contenham um critério, mas exclua um critério diferente

7

Eu tenho uma árvore de código-fonte e estou procurando todos os arquivos que contenham uma determinada palavra e não devem conter uma segunda palavra. Isso, porque eu preciso atualizar arquivos antigos para incluir algum código mais novo.

Eu sei que posso usar find, mas eu sinto que se eu tentar encadear declarações do grep ele não funcionará porque a segunda declaração do grep vai procurar os resultados do primeiro e depois eu me perdi.

Eu tentei:

find . -type f -name "*.c" -exec grep -Hl "ABC" {} \; | grep -L "123"

E isso não funcionou totalmente. Qualquer ajuda seria apreciada.

    
por the_gesslar 08.10.2016 / 19:08

3 respostas

12

Como o status de saída de grep indica se ele encontrou ou não uma correspondência, você deve ser capaz de testá-lo diretamente como um predicado find (com a negação necessária, ! ou -not ), por exemplo

find . -type f -name "*.c" \( -exec grep -q "ABC" {} \; ! -exec grep -q "123" {} \; \) -print

-q faz grep sair silenciosamente na primeira correspondência - não precisamos ouvi-la porque deixamos find imprimir o nome do arquivo.

    
por 08.10.2016 / 19:27
7

Como você já está usando as extensões do GNU:

find . -type f -size +2c -name "*.c" -exec grep -l --null ABC {} + |
  xargs -r0 grep -L 123

Se você quiser fazer outra coisa com esses arquivos:

find . -type f -size +2c -name "*.c" -exec grep -l --null ABC {} + |
  xargs -r0 grep -L --null 123 | xargs -r0 sh -c '
    for file do
      something with "$file"
    done' sh {} +

Ou com zsh ou bash :

find . -type f -size +2c -name "*.c" -exec grep -l --null ABC {} + |
  xargs -r0 grep -L --null 123 |
  while IFS= read -rd '' file; do
    something with "$file"
  done
    
por 08.10.2016 / 19:59
0

Para restrições complexas, prefiro usar uma linguagem de programação: Awk

find -name '*.c' \
   -exec awk -v RS="
find -name '*.c' \
   -exec awk -v RS="%pre%" '/ABC/ && !/123/{print FILENAME}' {} \; 
" '/ABC/ && !/123/{print FILENAME}' {} \;
    
por 16.03.2018 / 10:21

Tags