Hello all,

My question is about grep as a command line program...

How can I tell grep to only search inside files that end in ".php"?

The command that I am using now is:
grep -r "some_string" some_directory

Thanks!

-Dave

Dani AI

Generated

A short, practical summary that builds on and : the shell/backtick style expands every filename into the command line and will hit the system argument-size limit (the familiar "Argument list too long"). Two robust, different fixes are recommended — one that aggregates many files into fewer grep invocations, and one that safely handles names with spaces or newlines.

Use find's aggregated exec (runs grep on batches of files, faster than running once per file):

find /path/to/site -type f -name '*.php' -exec grep -nH 'some_string' {} +

Or use null-separated output piped to xargs so filenames with spaces/newlines are safe:

find /path/to/site -type f -name '*.php' -print0 | xargs -0 grep -n 'some_string'

Both approaches avoid shell expansion limits; the -exec ... + form builds long command lines and is efficient, while -print0 | xargs -0 protects against weird filenames. (gnu.org)

Notes and extras: if the installed grep supports recursive include/exclude flags, that is the cleanest single-command route (check grep --version). GNU grep can color fields such as the filename by setting GREP_COLORS and using --color; for example:

GREP_COLORS='fn=01;32' grep --color=always -n 'some_string' file.php

Use xargs -r (no-run-if-empty) to avoid running grep when no files are found, consider -I/-a options to skip binaries, and for very large codebases consider fast code-aware search tools (ripgrep/ack). (man7.org)

Recommended Answers

All 9 Replies

grep -r --include=*.php "some_string" some_directory

works in GNU grep 2.5.1

post output of `grep --version` and `grep --help` if that doesn't work... there might be another way.

Thanks for the reply Matt. But that didn't seem to work as expected.

I also noticed that there are two versions of grep available on our server:
/usr/bin/grep
/usr/local/bin/grep

If it type: "which grep"
I get: "/usr/bin/grep"

Here is the output of /usr/bin/grep --help

Usage: grep [OPTION]... PATTERN [FILE] ...
Search for PATTERN in each FILE or standard input.
Example: grep -i 'hello world' menu.h main.c

Regexp selection and interpretation:
  -E, --extended-regexp     PATTERN is an extended regular expression
  -F, --fixed-strings       PATTERN is a set of newline-separated strings
  -G, --basic-regexp        PATTERN is a basic regular expression
  -e, --regexp=PATTERN      use PATTERN as a regular expression
  -f, --file=FILE           obtain PATTERN from FILE
  -i, --ignore-case         ignore case distinctions
  -w, --word-regexp         force PATTERN to match only whole words
  -x, --line-regexp         force PATTERN to match only whole lines
  -z, --null-data           a data line ends in 0 byte, not newline

Miscellaneous:
  -s, --no-messages         suppress error messages
  -v, --invert-match        select non-matching lines
  -V, --version             print version information and exit
      --help                display this help and exit
  -Z, --decompress          decompress input before searching (HAVE_LIBZ=1)
      --mmap                use memory-mapped input if possible

Output control:
  -b, --byte-offset         print the byte offset with output lines
  -n, --line-number         print line number with output lines
  -H, --with-filename       print the filename for each match
  -h, --no-filename         suppress the prefixing filename on output
  -q, --quiet, --silent     suppress all normal output
      --binary-files=TYPE   assume that binary files are TYPE
                            TYPE is 'binary', 'text', or 'without-match'.
  -a, --text                equivalent to --binary-files=text
  -I                        equivalent to --binary-files=without-match
  -d, --directories=ACTION  how to handle directories
                            ACTION is 'read', 'recurse', or 'skip'.
  -r, --recursive           equivalent to --directories=recurse.
  -L, --files-without-match only print FILE names containing no match
  -l, --files-with-matches  only print FILE names containing matches
  -c, --count               only print a count of matching lines per FILE
      --null                print 0 byte after FILE name

Context control:
  -B, --before-context=NUM  print NUM lines of leading context
  -A, --after-context=NUM   print NUM lines of trailing context
  -C, --context[=NUM]       print NUM (default 2) lines of output context
                            unless overridden by -A or -B
  -NUM                      same as --context=NUM
  -U, --binary              do not strip CR characters at EOL (MSDOS)
  -u, --unix-byte-offsets   report offsets as if CRs were not there (MSDOS)

`egrep' means `grep -E'.  `fgrep' means `grep -F'.
With no FILE, or when FILE is -, read standard input.  If less than
two FILEs given, assume -h.  Exit status is 0 if match, 1 if no match,
and 2 if trouble.

Report bugs to <bug-gnu-utils@gnu.org>.

Here is the output of /usr/bin/grep --version

grep (GNU grep) 2.4d

Copyright (C) 1988, 1992-1998, 1999 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Here is the output of /usr/local/bin/grep --version

grep version 0.9
/usr/local/bin/grepusage: grep [-[AB] num] [-CEFGHLPRSVZabchilnoqsvwx] [-e patttern] [-f file]

Thanks!
-Dave

Try this; it relies on the 'find' command.

find . -name "*.php" -exec grep -H "some_string" {} \;

Which translates in english to.. search (find) in this folder (.) for files matching the filter ( -name ) *.php [ recursiveness should be default ]; when each file is found, execute grep, look for 'some_string', and pass in the found filename ( where the {} placeholder is ). Because that effectively executes grep once per file ( rather than once for many files ), you need the -H option to force grep to turn on the output of the filename; it wouldn't bother otherwise for a single file grep.

Messy eh? No wonder they put this functionality directly into grep for the next version...

EDIT: By the way, use that with the /usr/bin/grep.

Here's a simpler one in the same vein:

grep "some_string" `find some_folder -name "*.some_extension"`

i.e. grep "cerr" `find . -name "*.cpp"` note backticks (`) rather than single quotes around the find subcommand..

Many thanks Matt for the excellent help!

The command you posted works well:

grep "some_string" `find some_folder -name "*.some_extension"`

But there seems to be a limitation. I found that the command works as expected if used on a directory which does not contain many files. However, when I attempt to use it to search through all files in my site root directory, I get the following error:

/usr/bin/grep: Argument list too long.

My original problem to solve was how to search the contents of all PHP files within a website for a given text string.

Any further advice?

Thank you!
-Dave

lol.. didn't think of that.

did you try the first one I posted? that shouldn't hit the same problem.. because grep is opened with one line of arguement at a time.

otherwise; try this one:

find some_dir -name "*.some_ext" | xargs -l10 grep "some_expr"

looks similar to the find . -name "*.php" -exec grep -H "some_string" {} \; one; but it lets find collect the entire set of files and pipe them to the xargs command, which splits the set into blocks of 10 lines ( controlled using the -l flag ), and calls grep with those blocks of files as the last argument( s )..

with the split line set to 10; this one seems to run much, much faster than the other three ways.. You could change -l10 to be higher or lower, if you set it to 1 though you'll need to add the -H flag to grep again.

That solved my problem! (with a small correction)

I found that your command as posted did not work:

find some_dir -name "*.some_ext" | xargs -l10 grep "some_expr"

I got an error that "-l" was an illegal option. I looked at the man page for xargs and found that it should actually be "-L"

So here's the final command line magic that does exactly what I want:

find some_dir -name "*.some_ext" | xargs -L10 grep "some_expr"

Many thanks once again to Matt for the excellent suggestions!

Regards,
Dave

>>find some_dir -name "*.some_ext" | xargs -l10 grep "some_expr"

This helped. Thanks.

ps: I used unix utils in windows.

Guys is there a way to make the file name appear in color with the last command:

find some_dir -name "*.some_ext" | xargs -L10 grep "some_expr"

?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.