Reputation: 537
On Mac OS X, I have a bash script like this:
# Directories excluded from grep go here.
EXCLUDEDIR="--exclude-dir={node_modules,.git,tmp,angular*,icons,server,coffee}"
# This grep needs to include one line below the hit.
grep -iIrn -A1 $EXCLUDEDIR -e "class=[\"\']title[\"\']>$" -e "<div class=\"content" . > microcopy.txt
but it seems to be ignoring $EXCLUDEDIR
. If I simply use the --exclude-dir
directly, it works. Why won't it expand the variable and work right?
Upvotes: 2
Views: 508
Reputation: 16529
@tripleee correctly describes the problem, but there are two workarounds that I think are simpler (and, I think, more portable) than using an array: use eval
in the git
command, or use echo
in the variable assignment itself. The echo
method is preferable.
eval
# Directories excluded from grep go here.
EXCLUDEDIR="--exclude-dir={node_modules,.git,tmp,angular*,icons,server,coffee}"
# This grep needs to include one line below the hit.
eval grep -iIrn -A1 $EXCLUDEDIR # .... etc
This causes the braces to be expanded as if they had been typed literally. Note, however, that it may have some unintended side-effects if you're not careful; for instance, you may need to add some extra \
's to escape quotes and $
-signs.
echo
This is potentially safer than eval
, since you won't accidentally execute code hidden in the EXCLUDEDIR
variable.
# Directories excluded from grep go here.
EXCLUDEDIR="$(echo --exclude-dir={node_modules,.git,tmp,angular*,icons,server,coffee})"
# This grep needs to include one line below the hit.
grep -iIrn -A1 $EXCLUDEDIR # .... etc
Upvotes: 2
Reputation: 189936
The braces are technically an error. When they are in a variable, they are included verbatim, while when you type them directly as part of the command, Bash performs brace expansion, and effectively removes the braces from your expression.
bash$ echo --exclude-dir=moo{bar,baz}
--exclude-dir=moobar --exclude-dir=moobaz
bash$ x='moo{bar,baz}'
bash$ echo --exclude-dir=$x
--exclude-dir=moo{bar,baz}
The (not so simple) workaround is to list your parameters explicitly instead. This can be somewhat simplified by using an array to list the directory names you want to exclude (but this is not portable to legacy /bin/sh
).
x=(node_modules .git tmp angular\* icons server coffee)
EXCLUDEDIR="${x[@]/#/--exclude-dir=}"
The backslash in angular\*
is to pass this wildcard expression through to grep
unexpanded -- if the shell would expand the variable, grep
would not exclude directories matching the wildcard expression in subdirectories (unless they conveniently happened to match one of the expanded values in the current directory). If you have nullglob
in effect, an unescaped wildcard would simply disappear from the lists.
Upvotes: 6