How do I search for a string in a PHP file using `grep`?

You can try

grep -r --include=*.php "search string" /path/to/dir

I'd recommend that you use something like ctags rather than do it with a grep. However, if you want to, you can do something like

 find <top level dir> -name \*.php | xargs grep "class MyClass"

This of course assumes that you have just a single space between class and myClass which might not be true. It's easy to change the regexp to look for any number of whitespaces though.


If you use -r, you probably want to recursively search just the current directory:

grep -r 'class MyClass' .

Note the period on the end of the above.

What you told grep was that you wanted it to recursively search every *.php file or directory, but you likely didn't have any directories that ended in a .php extension. The above is the simplest possible way to do the search but also includes files of other types which is especially problematic when you have .svn directories everywhere. If you don't have a lot of other file types, the above is generally sufficient and works well.

Most incarnations of grep don't have a way to specify file extensions that can be searched, so you generally use find in conjunction with it:

find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} \;

-iname tells some versions of grep that you want to do a case-insensitive filename search, but many of the non GNU variants of find don't support it, so you could use -name instead.

The -exec option above has the side effect of invoking grep for every file, which is fairly costly.

Still other versions of grep support a + which tells find to append the arguments together to reduce the number of invocations of the executable:

find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} + \;

A frequently recommended way to reduce invocations is to use xargs which will fire off grep as few times as possible but as many times as necessary:

find <startDir> -iname \*.php | xargs grep "class[ \t]*MyClass"

xargs is smart enough to pass grep up to the maximum number of arguments supported on the command line, but the above variation doesn't handle certain characters like spaces very well. For example, were 'the file.php' a filename grep would receive 'the' as an argument and 'file.php' as an argument so both wouldn't be found. Instead we use:

find <startDir> -iname \*.php -print0 | xargs -0 grep "class[ \t]*MyClass"

print0 and -0 work together and use arguments followed by a null character so that the argument is completely and unambiguously identified.

f you ever have more than one space after class, or a tab, you might want to allow more characters by changing the regex: class[ \t]*MyClass

This post on StackOverflow has other examples and demonstrates how to exclude certain directories, like .svn directories.


Using the ever wonderful ack,

ack --php 'class MyClass'