10

I have the following function defined in my .bashrc, but for some reason the --exclude-dir option is not excluding the .git directory. Can anyone see what I've done wrong? I'm using Ubuntu 13.10 if that helps.

function fif # find in files { pattern=${1?" Usage: fif <word_pattern> [files pattern]"}; files=${2:+"-iname \"$2\""}; grep "$pattern" --color -n -H -s $(find . $files -type f) --exclude-dir=.git --exclude="*.min.*" return 0; } 
2
  • 3
    --exclude-dir option is only available in recent versions of GNU grep (>= 2.5.2) - reference. You may find this answer helpful Commented Nov 13, 2013 at 20:11
  • Isn't --exclude-dir supposed to be used in conjunction with -r (recursive) ? Commented Nov 13, 2013 at 20:23

2 Answers 2

18

Make sure not to include a trailing slash when you specify the directory to exclude. For example:

Do this:

$ grep -r --exclude-dir=node_modules firebase . 

NOT this:

$ grep -r --exclude-dir=node_modules/ firebase . 

(This answer not applicable to OP, but may be helpful for others who find --exclude-dir not to be working -- it worked for me.)

Sign up to request clarification or add additional context in comments.

3 Comments

Absolute paths seem to be a no-no as well. I was searching from root and wanted to avoid /dev, /proc, /sys, etc. --exclude-dir=/dev didn't work whereas --exclude-dir=dev worked as expected.
This is because --exclude-dir only matches on basenames. This means that referring to a nested folder won't work either, e.g. --exclude-dir=mydir/node_modules should be --exclude-dir=node_modules. See here: superuser.com/a/1096219
also watch out for typos not only in the trailing slash, but due to grep output eg outputting current dir ./snap/, not putting a dot in the beginning of location when its not a hidden one
12

Do a man grep on your system, and see what version you have. Your version of grep may not be able to use --exclude-dirs.

You're really better off using find to find the files you want, then use grep to parse them:

$ find . -name '.git' -type d -prune \ -o -name "*.min.*" -prune \ -o -type f -exec grep --color -n -H {} "$pattern" \; 

I'm not a fan of the recursive grep. Its syntax has become bloated, and it's really unnecessary. We have a perfectly good tool for finding files that match a particular criteria, thank you.

In the find program, the -o separate out the various clauses. If a file has not been filtered out by a previous -prune clause, it is passed to the next one. Once you've pruned out all of the .git directories and all of the *.min.* files, you pass the results to the -exec clause that executes your grep command on that one file.

Some people prefer it this way:

$ find . -name '.git' -type d -prune \ -o -name "*.min.*" -prune \ -o -type f -print0 | xargs -0 grep --color -n -H "$pattern" 

The -print0 prints out all of the found files separated by the NULL character. The xargs -0 will read in that list of files and pass them to the grep command. The -0 tells xargs that the file names are NULL separated and not whitespace separated. Some xargs will take --null instead of the -0 parameter.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.