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.

  • 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. 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 Jul 5 '11 at 16:14

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.


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

  • 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). Aug 6 '09 at 16:23

Use the grep that is better than grep, ack:

ack -l --java  "string" 
  • 3
    ack isn't installed on Mac OS X by default. 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
  • 1
    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. 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. 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" {} \;

grep -rl --include="*.java" simplestring *
  • 1
    This seems to be the best answer here - if grep does it all, why use find & xargs? 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 Jul 5 '11 at 16:18
  • Craig is right, I corrected my answer.
    – js.
    Jul 6 '11 at 14:40

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!


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!


Give this a go:

grep -rl "string" */*java
  • 1
    This gives "grep: */*java: No such file or directory" on Mac OS X. 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. 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. 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.

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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