7

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?

6
  • Duh what? find only finds file names, not contents.
    – Hello71
    Mar 12 '11 at 1:44
  • Ever heard of xargs? Or the -exec primary in find?
    – geekosaur
    Mar 12 '11 at 1:51
  • Hey man, I said that's what I used, not that it worked! Why do you think I'm asking? Plus, it was "something like" because I could never get it to work and had to google around for the xargs part.
    – tooshel
    Mar 14 '11 at 21:49
  • Sorry, that remark was directed at @Hello71. I'm still getting used to StackExchange etiquette.
    – geekosaur
    Mar 14 '11 at 21:58
  • Take a look at this post:theunixshell.blogspot.in/2014/03/…
    – Vijay
    Apr 18 '14 at 19:16
15
$ find . -type f -print0 | xargs -0 grep foo
$ grep -r foo . # GNU grep only

and in zsh with setopt extendedglob,

$ grep foo **/*(.)
3
  • Better: 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 '11 at 16:03
  • Still can't believe there isn't an easier way to do this. And I tried the "grep -r" and it didn't work. Why is it only GNU grep only and why isn't that on more systems?
    – tooshel
    Mar 14 '11 at 21:51
  • 1
    Because traditional 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.)
    – geekosaur
    Mar 14 '11 at 21:58
5

There's also ack, which is designed specifically for this kind of tasks and does subfolder search automatically.

1
  • An there is also ag which is way faster than ack.
    – mmoya
    Nov 15 '13 at 12:29
2

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

1

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.

5
  • Yeah, apparently not everyone has the fancy version of grep.
    – tooshel
    Mar 14 '11 at 21:54
  • @tooshel - didn't realise the non-GNU grep doesn't have that option. updated my answer :)
    – simon
    Mar 15 '11 at 1:40
  • -bash: ack: command not found
    – tooshel
    Mar 17 '11 at 22:05
  • Okay, I read the instructions to install ack . . . and I just tossed it in /bin so everyone can use it. Was that a bad idea?
    – tooshel
    Mar 17 '11 at 22:14
  • @tooshel: only if you don't want everyone to be able to use it...!
    – simon
    Mar 18 '11 at 2:52
0

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
>
1
  • 1
    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 '11 at 16:01
0

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

0

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

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.