-1

My grep version is grep (BSD grep) 2.5.1-FreeBSD and my operating system is OSX 10.13.3 (17D47)

I have a gitbook repo, and there is a temporary directory named _book which I want to ignore while using grep.

When I used grep -Fnrl mysql ./ --exclude-dir={_book}, it didn't exclude the _book directory. The result looks like

...
.//UTILITIES/my_utils/shell_scripts/get_several_days_mysql_data_log.sh
.//_book/search_jieba_index.dat
.//_book/LANGUAGES/awk/awk_magic.html

But the command grep -Fnrl mysql ./ --exclude-dir "_book" has gave me what I expected, the result looks like

...
.//UTILITIES/my_utils/shell_scripts/get_several_days_mysql_data_log.sh

I've searched on stackoverflow, and find a question which mentions the first command style and get 3 upvotes, so I guess it works under certain circumstances.
The question link is: Using grep with the --exclude-dir flag to exclude multiple directories

Why did this happen?
What should I do if I want to use the first command style to exclude _book successfully?

2

That post is taking advantage of bash's brace expansion:

$ printf "%s\n" --exclude-dir={a,b,c}
--exclude-dir=a
--exclude-dir=b
--exclude-dir=c

However, brace expansion is not applied when there is only one element, and the braces are left as-is:

$ printf "%s\n" --exclude-dir={a}
--exclude-dir={a}

Since the brace expansion is a feature of bash (and some other shells) but not grep, to grep it looks like you told it to exclude a directory named {_book}.

2

These aren't different "command styles." They're making use of a bash feature, not a grep feature.

Read up on it by running:

LESS='+/Brace Expansion' man bash

When you have comma-separated values inside of the braces, your shell expands them to multiple arguments before grep ever sees them.

Since you are only passing a single directory, you don't need brace expansion.

When you use braces with only a single item in between (no commas and no double periods to indicate range), your shell leaves the braces alone. You're left passing to grep the literal name {_book}, which is not the directory you want to exclude.


It's worth mentioning that you don't need the double quotes, either.

grep -Fnrl mysql ./ --exclude-dir _book

...will work just fine.

The double quotes don't hurt anything, but they aren't necessary either. You could use them on all arguments with the same result, as the quotes are removed by the shell—before grep ever sees them.

grep '-Fnrl' "mysql" './' "--exclude-dir" \_\b\o\o\k

You can even quote the command name itself 'grep', although this has a slightly different meaning. Specifically, it suppresses alias lookup. On Ubuntu systems, for instance, grep is usually aliased to grep --color=auto. Quoting "grep" (or any part of it) will bypass this alias.

gr\ep -Fnrl mysql ./ --exclude-dir _book

The moral of the story is, understand the quoting rules for the language you're writing in.

Or you can "make" errors with confusing results.

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.