Nick
Nick

Reputation: 457

bash parameter expansion as arguments to command

I'm having difficulty trying to pass a bash parameter to find as arguments.

Best explained via code:

$ echo $BASH_VERSION
4.1.2(1)-release

$ find /etc -path '*/init.d' 2>/dev/null | wc -l
2

$ args="-path '*/init.d'"
$ echo $args
-path '*/init.d'
$ find /etc $args 2>/dev/null | wc -l
0

$ set -x; !!
set -x; find /etc $args 2>/dev/null | wc -l
+ wc -l
+ find /etc -path ''\''*/init.d'\'''
0

Where are the extra '' quotes coming from in the set -x output?

I've tried a number of different ways to get this to work but haven't had success so far. This guide seems to indicate that this should be possible, since parameter expansion takes place before command execution: http://stuff.lhunath.com/parser.png

Upvotes: 0

Views: 209

Answers (1)

Charles Duffy
Charles Duffy

Reputation: 295272

Use an array:

args=( -path '*/init.d' )
find /etc "${args[@]}"

The reason the other approach doesn't work is discussed in detail in BashFAQ #50. In short: Quote characters are handled during syntax parsing -- before parameter expansion occurs. Thus, when quote characters come from parameter expansion, they're not parsed as syntax, but treated as any other data: Run through string-splitting and glob expansion, and passed through to the program being run.

The extra quotes/escaping in set -x output are just how the shell tells you that your primary quotes are data, distinguishing them from quotes that are present as syntax.

Upvotes: 4

Related Questions