I'm looking for a function name and the folder structure is deep and there are a lot of files to look though.
Usually I go with something like find * | grep functionname
but is that the best way?
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this community$ find . -type f -print0 | xargs -0 grep foo
$ grep -r foo . # GNU grep only
and in zsh
with setopt extendedglob
,
$ grep foo **/*(.)
find . -type f -print0 | xargs -0 grep /dev/null foo
, so that grep
always prints the matching file name. Or find . -type f -exec grep /dev/null {} +
, for implementations that have caught up with POSIX.2004 (which excludes OpenBSD at the moment).
Mar 12, 2011 at 16:03
grep
didn't have it (the idea was that if you wanted recursion, you used find
with grep
) and adding it after the fact to systems that have been working for years could break things. (GNU grep
doesn't behave quite identically to e.g. System V grep
.)
Mar 14, 2011 at 21:58
There's also ack
, which is designed specifically for this kind of tasks and does subfolder search automatically.
As an alternative to the find | xargs
responses, you might consider using ctags since you say you are searching not for text, but specifically for function names.
To do this you would run ctags
against your source to create a TAGS
file, and then run your grep
against the TAGS
file which will spit out lines in the following format:
{tagname}<Tab>{tagfile}<Tab>{tagaddress}
Where tagname
will contain the function name, tagfile
is the file it is in, and tagaddress
will be a vi command to get to that line. (Could be a just a line number.)
(Is there an easy way to do something similar with the various indices that eclipse builds, or to just query the eclipse database?)
what's wrong with grep -r
(== grep --recursive
)? Am I missing something here?
(+1 for ack
too -- I regularly use both)
edit: I found an excellent article detailing the possibilities and pitfalls if you don't have GNU grep
here. But, seriously, if you don't have GNU grep
available, getting ack
is even more highly recommended.
find . | xargs grep
will fail on filenames with spaces:
> echo test > "a b c"
> find . | xargs grep test
grep: ./a: No such file or directory
grep: b: No such file or directory
grep: c: No such file or directory
Note that even -print0 has this problem.
It's better in my opinion to use -exec grep
with find which will handle all filenames internally and avoid this problem:
> find . -exec grep test {} \;
test
>
find … -print0 | xargs -0 …
copes with arbitrary file names. All POSIX.2004-compliant implementations of find
allow find … -exec … {} +
, which invokes the command with multiple files at once. A better command is find . -type f -exec grep test /dev/null {} +
; the addition of /dev/null
is so that grep
will consistently print the file name when it finds a match.
Mar 12, 2011 at 16:01
If your disks are fast you may want to parallelize the grep:
find . -type f -print0 | parallel -0 grep foo
Watch the intro video to learn more about GNU Parallel: http://www.youtube.com/watch?v=OpaiGYxkSuQ
$ find -type f -print0 | xargs -r0 grep foo
-r
in xargs
avoids executing the command if there wasn't input. It's a GNU extension.
There is also ag
which is specifically designed for this and way better than ack
. It's available in recent Debian/Ubuntu versions in package silversearcher-ag.
find
only finds file names, not contents.xargs
? Or the-exec
primary infind
?