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.
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.
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.
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).
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"
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" {} \;
3
grep -rl --include="*.java" simplestring *
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
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!
0
Give this a go:
grep -rl "string" */*java
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.
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.
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