Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am using OS X.

I need to find files in a directory with the .php extension and the string 41 somewhere in the file's contents.

I tried using grep.

grep -R 41 *.php

This however only seemed to find files in the CWD and not in sub directories.

I also tried messing with find.

I wasn't able to figure this out.

What am I doing wrong?

share|improve this question
    
The 41 needs to be in the file name, or its content? – Daniel Beck May 31 '11 at 6:51
    
@Daniel In the contents, sorry if it wasn't clear. – alex May 31 '11 at 6:53
    
it does that because you told it to only search all files ending in php in the CWD - mind the expansion precedence... – Florenz Kley Jan 31 '13 at 1:00
up vote 10 down vote accepted

You need both.

find . -name '*.php' -type f -exec grep -q 41 {} \; -print
share|improve this answer
    
+1 Ignacio. Is it possible for it show the excerpt of the file where it found the substring, like grep normally does? Thanks. – alex May 31 '11 at 6:59
    
Sure. Just remove -q and the -print predicate. – Ignacio Vazquez-Abrams May 31 '11 at 7:00
    
Thank you. I really need to learn more about these things... – alex May 31 '11 at 7:01
    
As you do, you'll learn why find . -name '*.php' -type f -print0 | xargs -0 fgrep 41 -- is the next thing that people will suggest to you. – JdeBP May 31 '11 at 8:37
    
No need for xargs; BSD find understands -exec ... +. – Ignacio Vazquez-Abrams May 31 '11 at 8:38

in order for grep to work recursively, the argument to grep needs to include the directories it's expected to recurse.

looking at the following files

shiny:t fl$ find .
.
./evenmore
./evenmore/foo.php
./evenmore/inhere.php
./evenmore/no41in.php
./foo.php
./inhere.php
./morestuff
./morestuff/foo.php
./morestuff/inhere.php
./morestuff/no41in.php
./no41in.php
./stuff
./stuff/no41in.php

this does not work:

shiny:t fl$ grep -r 41 *.php
foo.php:41
inhere.php:41

because after path name expansion is done, the shell has processed the asterisk and the command line is now

shiny:t fl$ set -x
shiny:t fl$ grep -r 41 *.php
+ grep -r 41 foo.php inhere.php no41in.php
foo.php:41
inhere.php:41

there is no directory to descend in in the argument handed to grep. This however will descend in all directories present:

shiny:t fl$ grep -r 41 .
./evenmore/foo.php:41
./evenmore/inhere.php:41
./foo.php:41
./inhere.php:41
./morestuff/foo.php:41
./morestuff/inhere.php:41

whether that also processes dot-directories is left as an exercise to the reader :-)

share|improve this answer

If you use ack you can do ack 41 --php.

ack is like grep with built-in highlighting and line numbering and it's designed for searching source code.

share|improve this answer

I managed to use

grep 41 **/*.php

and it worked.

share|improve this answer

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .