I am using a command like this to find files with the word 'term' in them:

grep -l term *

But I now want to be able to find files which have two different words in them (let's call them termA and termB) - not necessarily on the same line. I want to find files with both terms in, not just files that have either term.

Now I could write a cumbersome bash script for this, but does grep, egrep, awk, sed or anything else have a tool that can help me?

Thanks in advance.


If your files contain no null bytes

In this case, you can use grep alone:

grep -Plz "termA.*termB|termB.*termA" *

How it works:

  • The Perl Compatible Regular Expressions termA.*termB and termB.*termA search for strings which have both terms in it.

  • The combined PCRE termA.*termB|termB.*termA matches all strings containing both terms.

  • Finally, the -z switch makes data lines end in null bytes instead of newlines.

By the way, there's no need to use -P. If you prefer to continue using POSIX Basic Regular Expressions, the syntax is similar:

grep -lz "termA.*termB\|termB.*termA" *

If your files contain null bytes

In this case, you'll need auxiliary tools:

(grep -l termA * ; grep -l termB *) | sort | uniq -d

How it works:

  • grep -l termA * ; grep -l termB * displays all files containing either of the terms. Files that contain both terms will be displayed twice.

  • sort sorts the output.

  • uniq -d only displays duplicate lines (required lines to be sorted).

  • Thanks - this is looking for the terms to be on the same line though.
    – Peter Howe
    Jul 11 '12 at 13:25
  • Sorry, I overlooked that requirement. I've updated my answer.
    – Dennis
    Jul 11 '12 at 13:42
  • Tnanks Dennis. The uniq -d was what I needed.
    – Peter Howe
    Jul 11 '12 at 14:51

You can use either the -e or -f options to search for multiple expressions (from man grep):

    -e PATTERN, --regexp=PATTERN
          Use  PATTERN  as  the  pattern.   This  can  be  used to specify
          multiple search patterns, or to protect a pattern beginning with
          a hyphen (-).  (-e is specified by POSIX.)

   -f FILE, --file=FILE
          Obtain  patterns  from  FILE,  one  per  line.   The  empty file
          contains zero patterns, and therefore matches nothing.   (-f  is
          specified by POSIX.)

So you would use this as:

$ grep -e termA -e termB *
  • Thanks. Not quite what I'm after. Your example (with -l to display the files) will give me files tat have either termA or termB in them. I want a list of files that have both terms in.
    – Peter Howe
    Jul 11 '12 at 13:00

grep supports regular expressions as far as I know. I use the following syntax to search multiple terms:

    grep 'termA\|termB' /i/am/a/path

you do need to use the escape character '\' before each '|' but with that I bvelieve you can use as many search strings as you want

  • Sorry, I've clarified it in the question now, but I'm after a list of files with both terms in. This would give me a list of files with either in.
    – Peter Howe
    Jul 11 '12 at 13:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.