Take the 2-minute tour ×
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 6 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

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

share|improve this answer
3  
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 at 16: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.

#!/bin/bash

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

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
    
One moment please, that needs a little tweak... –  Josh Nov 6 '09 at 13:00
    
Ok, tweaked. I'm not 100% satisfied with it though... –  Josh Nov 6 '09 at 13:03
1  
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

Your Answer

 
discard

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.