58

I am searching through a Ruby on Rails application for a word using grep on OSX, and I would like to exclude directories that match a certain pattern.

I am using the following command:

grep -inRw -E 'direct' . --exclude-dir -E 'git|log|asset'

This command is not doing what I thought it would do. Here is how I thought it would work:

  • i - case insensitive search
  • n - print line number in which pattern is found
  • R - search recursively
  • w - I only want whole words - i.e., match "direct" but not "directory"
  • -E - use extended regular expression
  • 'direct' - the regular expression I want to match
  • . - search in the current directory
  • --exclude-dir -E 'git|log|asset' - exclude directories that match git or log or asset.

In terms of the exclude directories, the command still ends up searching in the './git' and './log' directories, as well as in './app/assets'

I'm obviously lacking a fundamental piece of knowledge, but I do not know what it is.

4 Answers 4

70

It's pattern as in globs not pattern as in regex. Per the info page:

--exclude-dir=GLOB

Skip any command-line directory with a name suffix that matches the pattern GLOB. When searching recursively, skip any subdirectory whose base name matches GLOB. Ignore any redundant trailing slashes in GLOB.

So, you either use the switch multiple times or, if your shell supports brace expansion, you could golf it shorter and have the shell expand the list of patterns e.g.:

grep -inRw -E 'direct' . --exclude-dir={git,log,assets}

to exclude directories named git, log and assets or e.g.

grep -inRw -E 'direct' . --exclude-dir={\*git,asset\*}

to exclude directory names ending in git or starting with asset.

Note that the shell expands the list only if there are at least two dirnames/globs inside braces.

6
  • Very interesting. I guess I should look up what a glob is. Commented May 12, 2016 at 0:24
  • 1
    I'm sorry but none of these seem to be working. Would it help if I if I said that I'm using this version of grep: grep (BSD grep) 2.5.1-FreeBSD? Commented May 12, 2016 at 1:10
  • I'm stumped because I'm reading the manual for bsd grep (freebsd.org/cgi/man.cgi?query=grep&sektion=&n=1) and there's not mention of --exclude-dir. Boo. Commented May 12, 2016 at 2:21
  • 2
    OK - I see the problem now. This must be a modified version of grep used by the Apple system only. I am on Mac OS X. I'm sorry for the confusion here. I'm sure there's a forum somewhere else on stackexchange I can post to. Commented May 12, 2016 at 2:23
  • @user245185 are you on BSD or on OSX? Both are on topic here, but please edit your question and tell us what OS you are using. The behaviors of the standard tools differ between implementations as you're discovering. Commented May 12, 2016 at 8:49
19

--exclude-dir does not understand |.

You can, however, get the same effect by specifying --exclude-dir multiple times, one for each directory that you want to exclude:

grep -inRw -E --exclude-dir 'asset' --exclude-dir 'git' --exclude-dir 'log' 'direct'
4
  • 1
    It worked for me. I wanted to exclude home directory but it didn't work with other options like --exclude-dir={home}. I worked when I typed --exclude-dir 'home' Commented Aug 14, 2019 at 10:05
  • I can confirm that Mubin, the parentheses {...} don't have any effect for me either. Commented Oct 21, 2020 at 12:27
  • 1
    @MubinIcyer @AndreasL. Just a thought: {…} is a Bash construct — so if you have a different shell, it may not support it. 🤔 linux.com/topic/desktop/all-about-curly-braces-bash Commented Oct 27, 2022 at 10:48
  • @MubinIcyer you must have at least 2 globs, e.g. --exclude-dir={home,somethingelse}. See unix.stackexchange.com/q/433729 Commented Oct 12, 2023 at 9:44
15

This is what I was doing wrong: input to --exclude-dir is dir-name(s) and not pathname(s). directory names cannot contain /.

Following works:

grep -r --exclude-dir={cache,lib} pattern /home/ /var/

Following doesn't work:

grep -r --exclude-dir={/var/cache,/var/lib} pattern /home/ /var/
1
  • Indeed, that would explain a lot. The usability of grep is awful. Commented Feb 7 at 1:09
0

Please use this:

grep -inRw -E 'direct' folder/ --exclude-dir={\*git\*,\*log\*,\*assets\*}

or current folder

grep -inRw -E 'direct' . --exclude-dir -E 'git|log|asset'
0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.