grep all .java files in a directory for a particular string

12

7

How would I search all .java files for a simple string (not a regex) in the current directory and all sub-directories on Mac OS X? I just want to print a list of file and directory names that match.

John Topley

Posted 2009-07-15T20:06:45.357

Reputation: 1 558

Thanks for asking this so I don't have to. Now I just have to figure out how to exclude ".git" and I'm done for a bit. – Dan Rosenstark – 2010-11-16T21:13:32.977

I think js's answer is more concise, still sucks you have to type out --include, but still. Could probably just write an alias to hide that – Craig Tataryn – 2011-07-05T16:14:57.890

Answers

19

And the always popular

find . -name '*.java' | xargs grep -l 'string'

EDIT (by Frank Szczerba):

If you are dealing with filenames or directories that have spaces in them, the safest way to do this is:

find . -name '*.java' -print0 | xargs -0 grep -l 'string'

There's always more than one way to do it.

David Mackintosh

Posted 2009-07-15T20:06:45.357

Reputation: 3 728

mdfind is a more OSXy way to do this! – None – 2011-10-10T20:43:14.557

11

The traditional UNIX answer would be the one that was accepted for this question:

find . -name '*.java' | xargs grep -l 'string'

This will probably work for Java files, but spaces in filenames are a lot more common on Mac than in the traditional UNIX world. When filenames with spaces are passed through the pipeline above, xargs will interpret the individual words as different names.

What you really want is to nul-separate the names to make the boundaries unambiguous:

find . -name '*.java' -print0 | xargs -0 grep -l 'string'

The alternative is to let find run grep for you, as Mark suggests, though that approach is slower if you are searching large numbers of files (as grep is invoked once per file rather than once with the whole list of files).

Frank Szczerba

Posted 2009-07-15T20:06:45.357

Reputation: 505

You can also use the "--replace" option in xargs to deal with filenames having spaces in them: ... | xargs --replace grep 'string' '{}' ({} would be replaced by the filename) – arathorn – 2009-08-06T15:41:12.197

1Modern versions of find (including the one installed on OS X) support "-exec <command> {} +" where the plus sign at the end (instead of ;) tells find to replace {} with "as many pathnames as possible... This is is similar to that of xargs(1)" (from the man page). – Doug Harris – 2009-08-06T16:23:42.703

7

Use the grep that is better than grep, ack:

ack -l --java  "string" 

bortzmeyer

Posted 2009-07-15T20:06:45.357

Reputation: 1 083

In the case of ack, it's a single Perl program with no module dependencies. If you can "install" programs in your ~/bin directory, then you can just as easily "install" ack. – Andy Lester – 2010-05-03T18:53:39.837

3ack isn't installed on Mac OS X by default. – John Topley – 2009-07-15T20:25:06.343

I don't know what "by default" means. On many OS, you choose what you install so it is difficult to find programs which are always present. At a time, a C compiler was always there and Perl was uncommon... – bortzmeyer – 2009-07-15T20:34:37.787

1It means that it's part of the standard OS install. I have the developer tools installed on my Mac and they don't install ack. You have to install it yourself. If you have it, then it's a nice syntax. – John Topley – 2009-07-15T20:41:48.020

4

This will actually use a regex if you want, just stay away from the metacharacters, or escape them, and you can search for strings.

find . -iname "*.java" -exec egrep -il "search string" {} \;

Mark Thalman

Posted 2009-07-15T20:06:45.357

Reputation: 990

3

grep -rl --include="*.java" simplestring *

js.

Posted 2009-07-15T20:06:45.357

Reputation: 225

1This seems to be the best answer here - if grep does it all, why use find & xargs? – Peter Gibson – 2010-07-13T02:05:49.903

FYI, given what's asked in the question, it should be small "l" not big "L" in that command – Craig Tataryn – 2011-07-05T16:18:45.290

Craig is right, I corrected my answer. – js. – 2011-07-06T14:40:24.550

1

Since this is an OSX question, here is a more OSX specific answer.

Skip find and use Spotlight from the command line. Much more powerful!

COMMAND LINE SPOTLIGHT – FIND MEETS GREP

Most people don’t know you can do Spotlight searches from the command line. Why remember all the arcane find and grep options and what not when you can let Spotlight do the work for you. The command line interface to Spotlight is called mdfind. It has all the same power as the GUI Spotlight search and more because it is scriptable at the command line!

user22908

Posted 2009-07-15T20:06:45.357

Reputation:

0

Give this a go:

grep -rl "string" */*java

dwj

Posted 2009-07-15T20:06:45.357

Reputation: 1 384

1This gives "grep: /java: No such file or directory" on Mac OS X. – John Topley – 2009-07-15T20:12:35.950

The problem here is that it will only find *.java files one level deep. See Mark Thalman's answer for IMHO the proper way to do it. – Ludwig Weinzierl – 2009-07-15T20:17:51.307

Sorry, not at my Mac. Doesn't the Mac version of grep have the -r (recursive) flag? – dwj – 2009-07-15T20:36:57.140

It does, but that was the output that I got when searching for a string that I know is in the files. – John Topley – 2009-07-15T20:40:24.560

0

You could also use a GUI program like TextWrangler to do a more intuitive search where the options are in the interface.

Mark Thalman

Posted 2009-07-15T20:06:45.357

Reputation: 990

0

grep "(your string)" -rl $(find ./ -name "*.java")

If you want to ignore case, replace -rl with -irl. (your string) may also be a regex if you ever see the need.

laughing_man

Posted 2009-07-15T20:06:45.357

Reputation: 101