10

I want to find all occurences of foo in a large file system maintained by SVN but I don't want to match anything contained in any .svn directory.

I get immediate matches when I do grep -l -e 'foo' * but when I try and exclude the svn directories with grep -l -e 'foo' --exclude-dir=".svn" the command just hangs.

What am I doing wrong?

11

--exclude-dir does not supplant the need to list files on the command line. You are "hanging" because grep is waiting for standard input.

grep -l -e 'foo' --exclude-dir=".svn" *

Consider using ack, which excludes .svn and similar folders (and has many other features) by default.

  • 2
    Cleaner if you change * to ., in case there are other hidden folders that should be searched. – Kevin Apr 2 '12 at 17:51
  • or perhaps you want to use --recursive . instead, seeing as the OP already has GNU grep. – jw013 Apr 2 '12 at 17:53
  • Personally, I have shopt -s dotglob in Bash, so * already contains dot-files. -r is nice, but ack does that by default too :) – ephemient Apr 2 '12 at 17:54
5

You might be interested in ack. It does recursive searching (and other grep-like operations), and excludes directories such as .svn or .git by default.

  • As a followup on this, I currently use ag, which similar, but faster. – WhyNotHugo Jul 4 '17 at 20:24
2

The grep --exclude-dir... solution should be fine, but just to show another way, you can do this with find's -prune:

find -name .svn -prune -o -type f -exec grep -l "$pattern" {} +

If you want to execute something further, find is better than a plain grep -r:

find -name .svn -prune -o -type f -exec grep -q "$pattern" {} \; -exec ./process {} \;
1

If you do not want to grep into directories such as .svn ever you can set the $GREP_OPTIONS variable to exclude it as below:

export GREP_OPTIONS="--exclude-dir=\*/.svn/\*"

Just add this line to your .bashrc and your recursive greps will no more enter into .svn directories. Of course, it can be as rich as you want:

export GREP_OPTIONS="--exclude-dir=\*/.svn/\* --exclude-dir=\*/.hg/\* --exclude-dir=\*/.git/\* --exclude=\*~"
  • 1
    I personally do this using an alias so that I can bypass the exclusion list if I need to actually search inside those folders I can just use bare grep without having to unset/null out the variable. It also lets me maintain a list of folders that I can easily expand and have automatically added to my list of exclusions without having to do more typing. – dragon788 Jul 2 '17 at 6:08
  • That's a good approach. It also has the advantage that, if you need to grep into the folders, you will not forget you set a variable. (Not that I had ever needed to grep them.) But TBH these days I use ag (an ack clone) for these things ^^ – brandizzi Jul 3 '17 at 10:10
0

Here's an awk solution as well:

find . | awk '$0 !~ /.svn/{print}' | awk '/foo/{print}'

Basically, from all files, prune those that match /.svn/ and then, out of those, print only these ones that match /foo/. I also like this solution as you can easily use the results with ls. For example, you can use

ls -tl $(find . | awk '$0 !~ /.svn/{print}' | awk '/foo/{print}')

to see a list view sorted by modification date. Also, it's nice to have the full path of the results if you want to do something else with them (open them, execute, etc.)

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.