Here we go:
I need to query php files which both have a TODO statement as well as my name.
Both strings could be anywhere in the document (ie. line) and be positioned anywhere on 0-infinite lines (position 0-n).
How to grep query for my name:
find -name '*.php' -exec grep -in "fincken" {} +
output:
./some/file.php:51: ramon fincken
./somefile.php:2: rfincken
How to grep query for the TODOs
find -name '*.php' -exec grep -n "TODO" {} +
output:
./some/file.php:53: // TODO: foobar!
./some/otherfile.php:53: // TODO: foobar?
I need to combine both grep queries (or their results) so I am expecting this as result:
./some/file.php
I have tried operators in one grep, but they expected both strings on the same line and in a particular order or .. came up with all results (OR .. OR) instead of ( AND )
this line looks ugly, but it should give what you want:
find whatever...|xargs grep -il 'fincken'
|xargs grep -il 'todo'
|xargs grep -in -e'todo' -e'fincken'
The output would look like:
/foo/bar/file : 100:TODO
/foo/bar/file : 101:fincken
only files with both TODO
and fincken
would be listed.
Ask the first grep
to return just the file name and then pipe to another grep
:
find -name '*.php' -exec grep -li "fincken" {} + | xargs grep -l "TODO"
From man grep
, -l
(L) returns file name. This way, the find
comman will return a list of files that will be processed one by one through the xargs
command.
Your output will be the list of files which contain both "fincken" and "TODO". You can of course pipe more xargs grep -l
if you want to add more words to find.
You can also do use of grep
alone like this, using -R
to do a recursive search:
grep -Rl --include="*php" "TODO" * | xargs grep -il "fincken"
Note I moved the TODO
grep to be done in the first place, because you use -i
for "fincken" and it is way slowlier. This way, the grep -i
will only be run on the already filtered results.
You can pipe the first grep through a second one, get the name of the file and skip repetitions:
find -name '*.php' -exec grep -in "fincken" {} + | grep TODO | cut -d: -f1 | uniq
People are making this more complicated then it needs to be. -exec
will take the exit code of the command it runs and use it logically in find
. So you can just do
find -name '*.php' -exec grep -iq "fincken" {} \; -exec grep -iq "TODO" {} \; -print
Which will get to the -print
only if both -exec
blocks return 0.