Sign up ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I use recursive grep a lot to find source files with specific content.

grep -Rni "myfunc" .

On large codebases, this can get slow, so I use --incldue to restrict/whitelist extensions.

grep -Rni --include=*.java "myfunc" .

However, it would be more efficient to exclude (prune) whole subdirectories, I'm thinking:

grep -Rni --exclude=/.svn/ "myfunc" .

But the --exclude only supports file patterns like *.java above. How can I exclude directories?

share|improve this question

5 Answers 5

up vote 7 down vote accepted

You might look into ack.

I've just started using it but it seems well-suited for this.

share|improve this answer
ack looks pretty good. nice that it intuitively excludes unwanted files. the --nogroup option gives a similar output to grep -Rni – gabor Feb 12 '10 at 19:48
grep -r --exclude-dir=dev --exclude-dir=sys --exclude-dir=proc PATTERN data


share|improve this answer
Note that this recursively excludes. ./dev will be excluded ALONG WITH ./foo/bar/dev. Use --exclude-dir=./dev to only apply to the first case. – Cory Walker May 13 '13 at 14:08
You can also shorten this a bit by globbing: bash grep -r --exclude-dir={dev,sys,proc} PATTERN data The only problem with globbing is that I cannot get it to work in my bash. In that case I have to keep them separate. – b01 Aug 13 '14 at 16:21
Also noted that {} only works if you put more than 1 entries, that means --exclude-dir={home,.svn} is works but --exclude-dir={.svn} will not works. It waste my time to figure out why {} doesn't work because i test with 1 entry in the first place. – 林果皞 Apr 28 at 7:21

you can use find instead:

find . -not -path "*/.svn*" -not -type d -exec grep -ni "myfunc" {} \; -print

OK, so that's a little backwards, you get the grep results first and then the path. Maybe someoe else has a better answer?

share|improve this answer
ok, i like that a lot. of course find is a lot more flexible. the only difference between the output is that "grep -Rni" will print the file name for each match, whereas "find -exec grep" will print the filename on one line and then one line for each match (with line number and line content). using "grep -Hni" forces the filename to be displayed on each line – gabor Nov 6 '09 at 13:59

Here's a full example from a script in one of my projects that might help, I call this file "all_source" (marked as executable) and put it in my project's root dir then call it like grep myfunc $(./all_source) the sort at the end of the script is totally optional.


find . \
    -type d \( \
            -wholename './lib' -o \
            -wholename './vc6' -o \
            -name 'gen' -o \
            -name '.svn' \
            \) -prune -o \
    -type f \( \
            -name '*.h' -o \
            -name '*.cpp' -o \
            -name '*.c' -o \
            -name '*.lua' -o \
            -name '*.*awk' \) -print \
    | sort

This script returns all the file names in the project that match *.h, *.cpp, *.c, *.lua, *.*awk, but doesn't search in all folders named .svn and gen folders as well as skipping the folders for ./lib and ./vc6 (but only the ones right off the project root). So when you do grep myfunc $(./all_source) it only greps in those files. You'll need to call this from the root dir of the project as well.

share|improve this answer

There is also the -prune option to find:

 find . -path "*/.svn*" -prune -o -not -type d -exec grep -ni "myfunc" {} \; -print
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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