When I want to perform a recursive grep search in the current directory, I usually do:
grep -ir "string" . But that command searches inside all kinds of files, including binary files (pictures, audio, video, etc...) which results in a very slow search process.
If I do this, for example, it doesn't work:
grep -ir "string" *.php It doesn't work because there are no PHP files inside the current directory, but inside some of the subdirectories in the current directory, and the subdirectories' names don't end with ".php" so grep doesn't look inside them.
So, how can I do a recursive search from the current directory but also specifying filename wildcards? (i.e: only search in files which end in a specific extension)
3 Answers
Use grep's --include option:
grep -ir "string" --include="*.php" . 4If you have a version of grep that lacks the --include option, you can use the following. These were both tested on a directory structure like this:
$ tree . ├── a ├── b │ └── foo2.php ├── c │ └── d │ └── e │ └── f │ └── g │ └── h │ └── foo.php ├── foo1.php └── foo.php Where all the .php files contain the string string.
Use
find$ find . -name '*php' -exec grep -H string {} + ./b/foo2.php:string ./foo1.php:string ./c/d/e/f/g/h/foo.php:stringExplanation
This will find all
.phpfiles and then rungrep -H stringon each of them. Withfind's-execoption,{}is replaced by each of the files found. The-Htellsgrepto print the file name as well as the matched line.Assuming you have a new enough version of
bash, useglobstar:$ shopt -s globstar $ grep -H string **/*php b/foo2.php:string c/d/e/f/g/h/foo.php:string foo1.php:stringExplanation
As explained in the bash manual:
globstar
If set, the pattern ‘**’ used in a filename expansion context will match all files and zero or more directories and subdirectories. If the pattern is followed by a ‘/’, only directories and subdirectories match.
So, by running
shopt -s globstaryou are activating the feature and Bash'sglobstaroption which makes**/*phpexpand to all.phpfiles in the current directory (**matches 0 or more directories, so**/*phpmatches./foo.phpas well) which are then grepped forstring.
Use */*.php
This makes grep search one level of subdirectory
3