How can I find all files in a folder with a certain text string and an extension?

5

6

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?

alex

Posted 2011-05-31T06:46:32.517

Reputation: 3 604

The 41 needs to be in the file name, or its content? – Daniel Beck – 2011-05-31T06:51:38.350

@Daniel In the contents, sorry if it wasn't clear. – alex – 2011-05-31T06:53:40.543

it does that because you told it to only search all files ending in php in the CWD - mind the expansion precedence... – Florenz Kley – 2013-01-31T01:00:13.453

Answers

10

You need both.

find . -name '*.php' -type f -exec grep -q 41 {} \; -print

Ignacio Vazquez-Abrams

Posted 2011-05-31T06:46:32.517

Reputation: 100 516

+1 Ignacio. Is it possible for it show the excerpt of the file where it found the substring, like grep normally does? Thanks. – alex – 2011-05-31T06:59:49.460

Sure. Just remove -q and the -print predicate. – Ignacio Vazquez-Abrams – 2011-05-31T07:00:18.597

Thank you. I really need to learn more about these things... – alex – 2011-05-31T07:01:05.370

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 – 2011-05-31T08:37:30.727

No need for xargs; BSD find understands -exec ... +. – Ignacio Vazquez-Abrams – 2011-05-31T08:38:53.027

that's a workaround, not an answer. – Florenz Kley – 2013-01-31T01:14:17.887

1

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.

Andy Lester

Posted 2011-05-31T06:46:32.517

Reputation: 1 121

1

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 :-)

Florenz Kley

Posted 2011-05-31T06:46:32.517

Reputation: 1 453

0

I managed to use

grep 41 **/*.php

and it worked.

alex

Posted 2011-05-31T06:46:32.517

Reputation: 3 604