Reputation: 26202
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
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
Reputation: 107759
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
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
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