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.
5 Answers
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?– AscoobisMar 29, 2013 at 1:02
-
-H option of egrep then to output filepaths. str1|str2|str3..etc would work - is that what you mean by generalize? Mar 29, 2013 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" '{}' \;
– AscoobisMar 29, 2013 at 1:42
Don't forget that your shell is way more convenient than find
if you only want to find the files by name!
Bash:
shopt -s nullglob globstar
grep -lE 'str1|str2' /home/smith/source/**/*.{html,php}
Fish:
grep -lE 'str1|str2' /home/smith/source/**.{html,php}
If you use ack
(see http://beyondgrep.com) you can do this:
ack --php --html -l 'str1|str2' /home/smith/source
-
-
Reimplemented by a number of different tools, many of which are listed here: beyondgrep.com/more-tools Dec 23, 2016 at 22:07