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?

6 Answers 6


You might look into ack.

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

  • ack looks pretty good. nice that it intuitively excludes unwanted files. the --nogroup option gives a similar output to grep -Rni
    – gabor
    Feb 12, 2010 at 19:48
  • 2
    Ack is a bit slow. You can try The Silver Searcher (Ag) or ripgrep (rg).
    – user31389
    Oct 19, 2016 at 14:31
grep -r --exclude-dir=dev --exclude-dir=sys --exclude-dir=proc PATTERN data

Source: https://stackoverflow.com/questions/2799246/grep-excluding-a-specific-folder-using

  • 18
    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. May 13, 2013 at 14:08
  • 4
    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, 2014 at 16:21
  • 3
    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, 2015 at 7:21
  • If you use {} with a single entry you probably need a unary comma to make it an array (not sure how Bash handles that). Instead of doing that I ended up making an alias in my .bash_aliases that loops over a list of folders I typically always want to exclude, eg .git, .svn, .hg, .cache, and then I add them via a loop with --exclude-dir $dir and then expand that array into the grep alias.
    – dragon788
    Jul 2, 2017 at 6:03

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?

  • 3
    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, 2009 at 13:59
  • Thank you for providing the only answer that worked for systems which are this crusty, without grep --exclude-dir, but still gotta be worked on
    – Dmitri DB
    Sep 19, 2016 at 10:21

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.


There is also the -prune option to find:

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

You can try doing this:

grep -R  "myfunc" . | grep -v path_to_exclude/

Eg: If you don't want to search the content in log files just do the following:

grep -R "myfunc" . | grep -v log/

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.