splungebob
splungebob

Reputation: 5415

Multiple keyword grep where all keywords must be found

I'm trying to find a better way to determine which files in a given directory contain all of a given set of search strings. The way I'm currently doing it seems awkward.

For example, if I want to find which files contain "aaa", "bbb", "ccc", and "ddd" I would do:

grep -l "aaa" * > out1
grep -l "bbb" `cat out1` > out2
grep -l "ccc" `cat out2` > out3
grep -l "ddd" `cat out3` > out4
cat out4
rm out1 out2 out3 out4

As you can see, this seems clumsy. Any better ideas?

EDIT: I'm on a Solaris 10 machine

Upvotes: 0

Views: 1307

Answers (2)

Olivier Dulac
Olivier Dulac

Reputation: 3791

something along this may help:

for file in * ; do
   matchall=1
   for pattern in aaa bbb ccc ddd ; do
      grep "$pattern" "$file" >/dev/null || { matchall=0; break ; }
   done
   if [ "$matchall" -eq "1" ]; then echo "maching all : $file" ; fi
done

(you can add patterns by replacing aaa bbb ccc ddd with something like $(cat patternfile))

For the ones interrested : it 1) loop over each file, and 2) for each file: it assumes this will match all patterns, and loops over the patterns: as soon as a pattern doesn't appear in the file, that pattern loop is exited, the name of that file is not printed, and it goes to check the next file. ie, it only print a file which has been through all the patterns without any setting "matchall" to 0.

Upvotes: 1

bikeshedder
bikeshedder

Reputation: 7487

You can use xargs to chain the grep calls together:

grep -l "aaa" * | xargs grep -l "bbb" | xargs grep -l "ccc" | xargs grep -l "ddd"

Upvotes: 1

Related Questions