Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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.

share|improve this question
    
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. –  Yar Nov 16 '10 at 21:13
    
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 Jul 5 '11 at 16:14

9 Answers 9

up vote 14 down vote accepted

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.

share|improve this answer
    
mdfind is a more OSXy way to do this! –  Jarrod Roberson Oct 10 '11 at 20:43

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

share|improve this answer
    
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 Aug 6 '09 at 15:41
1  
Modern 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 Aug 6 '09 at 16:23

Use the grep that is better than grep, ack:

ack -l --java  "string"
share|improve this answer
2  
ack isn't installed on Mac OS X by default. –  John Topley Jul 15 '09 at 20:25
    
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 Jul 15 '09 at 20:34
    
It 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 Jul 15 '09 at 20:41
    
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 May 3 '10 at 18:53

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" {} \;

share|improve this answer
grep -rl --include="*.java" simplestring *
share|improve this answer
1  
This seems to be the best answer here - if grep does it all, why use find & xargs? –  Peter Gibson Jul 13 '10 at 2:05
    
FYI, given what's asked in the question, it should be small "l" not big "L" in that command –  Craig Tataryn Jul 5 '11 at 16:18
    
Craig is right, I corrected my answer. –  js. Jul 6 '11 at 14:40

Give this a go:

grep -rl "string" */*java
share|improve this answer
    
This gives "grep: */*java: No such file or directory" on Mac OS X. –  John Topley Jul 15 '09 at 20:12
    
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 Jul 15 '09 at 20:17
    
Sorry, not at my Mac. Doesn't the Mac version of grep have the -r (recursive) flag? –  dwj Jul 15 '09 at 20:36
    
It does, but that was the output that I got when searching for a string that I know is in the files. –  John Topley Jul 15 '09 at 20:40

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

share|improve this answer

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

share|improve this answer
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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.