Sunday, June 3, 2012

Exclude .svn directories from grep

When I grep my Subversion working copy directory, the results include a lot of files from the .svn directories. Is it possible to recursively grep a directory, but exclude all results from .svn directories?

Source: Tips4all


  1. If you have GNU Grep, it should work like this:

    grep --exclude-dir=".svn"

    If happen to be on a Unix System without GNU Grep, try the following:

    grep -R "whatever you like" *|grep -v "\.svn/*"

  2. If you use ack (a 'better grep') it will handle this automatically (and do a lot of other clever things too!). It's well worth checking out.

  3. For grep >=2.5.1a

    You can put this into your environment (e.g. .bashrc)

    export GREP_OPTIONS='--exclude-dir=".svn"'

  4. psychoschlumpf is correct, but it only works if you have the latest version of grep. Earlier versions do not have the --exclude-dir option. However, if you have a very large codebase, double-grep-ing can take forever. Drop this in your .bashrc for a portable .svn-less grep:

    alias sgrep='find . -path "*/.svn" -prune -o -print0 | xargs -0 grep'

    Now you can do this:

    sgrep some_var

    ... and get expected results.

    Of course, if you're an insane person like me who just has to use the same .bashrc everywhere, you could spend 4 hours writing an overcomplicated bash function to put there instead. Or, you could just wait for an insane person like me to post it online:

  5. grep --exclude-dir=".svn"

    works because the name ".svn" is rather unique. But this might fail on a more generalized name.

    grep --exclude-dir="work"

    is not bulletproof, if you have "/home/user/work" and "/home/user/stuff/work" it will skip both. It is not possible to define "/*/work/*"
    to restrict the exclusion to only the former folder name.
    As far as I could experiment, in GNU grep the simple --exclude won't exclude directories.

  6. Two greps will do the trick:

    The first grep will get everything.
    The second grep will use output of first grep as input (via piping). By using the -v flag, grep will select the lines which DON'T match the search terms. Voila. You are left with all the ouputs from the first grep which do not contain .svn in the filepath.

    -v, --invert-match
    Invert the sense of matching, to select non-matching lines.

    grep the_text_you_want_to_search_for * | grep -v .svn

  7. I think the --exclude option of recursion is what you are searching for.