13

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.

0

3 Answers 3

18

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.

3
  • 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. Commented Oct 8, 2016 at 21:58
  • 2
    @steeldriver:  I believe that you could leave out the \( and the \). Commented Oct 9, 2016 at 6:27
  • Is grep "123" applied on results from first find/grep couple ? Commented Mar 7, 2018 at 14:17
8

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 
1

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

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

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.