How can i combine find and grep to search for str1 or str2, recursively, in all *.html and *.php files starting from a directory named /home/smith/source? The output only needs to list files (with path), not the actual matched string. i've tried many variations without success. There are lots of examples of how to do this for one file pattern or one string, but not multiple file patterns and multiple strings--recursively.


Others are all correct, but with a modern version of grep available they are overkill in my opinion. The following will recursively scan only files with .html or .php extensions and return the filename with path of each file with at least one line matching either str1 or str2. Note that the repeated -e options allow specification of multiple paths without using regex syntax to do so.

grep -r --files-with-matches --include '.html' --include '.php' -e str1 -e str2 /home/smith/source

One tool, one process, no extra forking or scanning of non-relevant files. Just requires a relatively recent version of gnu grep for the --include option, failing that you will have to do a multi-stage grep as proposed by others.

egrep 'string1|string2' /home/smith/source/*.{html,php}

or looking into any type of file recursively inside a directory,

egrep -R 'string1|string2' /home/smith/source

you can combine that with another egrep in the pipe :

egrep -R 'string1|string2' /home/smith/source | egrep '.html|.php'

Use egrep and use | to specify str1 or str2-:

find /home/smith/source -name \*.html -o -name \*.php -exec egrep -H 'str1|str2' {} \;
  • That shows matched text, not filenames, but that's OK (I made the update to the questions probably while you were answering the existing one). How can I generalize this if i want to search 3,4,5, or n file patterns? – Ascoobis Mar 29 '13 at 1:02
  • -H option of egrep then to output filepaths. str1|str2|str3..etc would work - is that what you mean by generalize? – suspectus Mar 29 '13 at 1:06
  • Yes, but I also meant to generalize the file pattern (e.g., *.php and *.html and *.txt and ...). This appears to do it: find /home/smiths/source -type f -regextype posix-egrep -regex ".*\.(php|html)$" -exec egrep -H -n "str1|str2|str3" '{}' \; – Ascoobis Mar 29 '13 at 1:42

If you use ack (see http://beyondgrep.com) you can do this:

ack --php --html -l 'str1|str2' /home/smith/source
  • Also reimplemented as ag and rg. Which I think is a testament to its musthaveness. – user2394284 Dec 22 '16 at 22:49
  • Reimplemented by a number of different tools, many of which are listed here: beyondgrep.com/more-tools – Andy Lester Dec 23 '16 at 22:07

Don't forget that your shell is way more convenient than find if you only want to find the files by name!


shopt -s nullglob globstar
grep -lE 'str1|str2' /home/smith/source/**/*.{html,php}


grep -lE 'str1|str2' /home/smith/source/**.{html,php}

Your Answer

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