7

I have a tree of source code and I am looking to find all files that contain a certain word and must not contain a second word. This, because I need to update older files to include some newer code.

I know I can use find, but I feel like if I try to chain grep statements it won't work because the second grep statement is going to be searching the results of the first and then I got lost.

I tried:

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

And this totally did not work. Any help would be appreciated.

12

Since the exit status of grep indicates whether or not it found a match, you should be able to test that directly as a find predicate (with the necessary negation, ! or -not) e.g.

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

-q makes grep exit silently on the first match - we don't need to hear from it because we let find print the filename.

  • Note that it runs at least one and up to two greps per C file. -q already stops at the first match. -m1 (a GNU extension) won't make any difference. – Stéphane Chazelas Oct 8 '16 at 21:58
  • 2
    @steeldriver:  I believe that you could leave out the \( and the \). – G-Man Oct 9 '16 at 6:27
  • Is grep "123" applied on results from first find/grep couple ? – Delphine Mar 7 '18 at 14:17
7

Since you're already using GNU extensions:

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

If you want to do something else with those files:

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 {} +

Or with zsh or 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
0

For complex constrains, I prefer using a programming language: Awk

find -name '*.c' \
   -exec awk -v RS="\0" '/ABC/ && !/123/{print FILENAME}' {} \; 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.