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, 2010 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, 2011 at 16:14

9 Answers 9


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, 2009 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, 2009 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, 2009 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, 2009 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, 2009 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, 2010 at 18:53
grep -rl --include="*.java" simplestring *
  • 2
    This seems to be the best answer here - if grep does it all, why use find & xargs? Jul 13, 2010 at 2:05
  • FYI, given what's asked in the question, it should be small "l" not big "L" in that command Jul 5, 2011 at 16:18
  • Craig is right, I corrected my answer.
    – js.
    Jul 6, 2011 at 14:40

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


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, 2009 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, 2009 at 20:17
  • Sorry, not at my Mac. Doesn't the Mac version of grep have the -r (recursive) flag?
    – dwj
    Jul 15, 2009 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, 2009 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.