Gandalf StormCrow
Gandalf StormCrow

Reputation: 26202

Search directory and sub-directories for pattern in a file

In linux, I want to search the given directoy and its sub-folders/files for certain include and exclude pattern.

find /apps -exec grep "performance" -v "warn" {} /dev/null \;

This echoes loads of lines from which search goes trough. I don't want that, I'd like to find files containing performance which do not contain warn. How do I do that?

Upvotes: 2

Views: 5337

Answers (4)

glenn jackman
glenn jackman

Reputation: 246807

If you want to find files that do not contain "warn" at all, grep -v is not what you want -- that prints all lines not containing "warn" but it will not tell you that the file (as a whole) does not contain "warn"

find /apps -type f -print0 | while read -r -d '' f; do
    grep -q performance "$f" && ! grep -q warn "$f" && echo "$f"
done

Upvotes: 0

To find files containing performance but not warn, list the files containing performance, then filter out the ones that contain warn. You need separate calls to grep for each filter. Use the -l option to grep so that it only prints out file names and not matching lines. Use xargs to pass the file names from the first pass to the command line of the second-pass grep.

find /apps -type f -exec grep -l "performance" /dev/null {} + | 
sed 's/[[:blank:]\"'\'']/\\&/g' |
xargs grep -lv "warn"

(The sed call in the middle is there because xargs expects a weirdly quoted input format that doesn't correspond to what any other command produces.)

Upvotes: 3

Rajish
Rajish

Reputation: 6795

Using -exec option of the find command is less effective than pipelining it to xargs:

find /apps -print0 | xargs -0 grep -n -v "warn" | grep "performance"

This, probably, also solves your problem with printing unwanted output. You will also probably want tu use the -name option to filter out specific files.

find /apps -name '*.ext' -print0 | xargs -0 grep -n -v "warn" | grep "performance"

Upvotes: 1

johnsyweb
johnsyweb

Reputation: 141790

Very close to what you have already:

find /apps -exec grep "performance" {} /dev/null \; | grep -v "warn"

Just pipe the output through a second call to grep.

Upvotes: 3

Related Questions