2

I have a script count_args that counts arguments:

#!/bin/sh
echo $#

If I call it with these options, it tells me it gets two arguments:

$ ./count_args --options '1 2'
2

But if I construct the arguments in a script test_args like so:

#!/bin/sh
ARGS="--options '1 2'"
./count_args ${ARGS}

...I get the result:

$ ./test_args 
3

Why is the '1 2' being split in the script? How can I avoid this in a POSIX compliant way, from the calling script? Is it possible to still store arguments in variables somehow so that I can separate them in more complex scripts (eg. having ARGS_1 and ARGS_2)?

Note that my /bin/sh is dash.

detly
  • 5,160

1 Answers1

3

In your first case, the arguments passed to count_args were interpreted by the shell, the shell saw two words --options and 1 2 then passed them to count_args.

With second case, Inside double quotes, all characters except $ and \ are treated as literal. It's too late for the shell to interpret the single quotes, the shell saw the content of $ARGS variable as a long string --options '1 2', all characters as literal and have no special meaning to the shell.

Using ${ARGS} without double quotes made it subjected to fields splitting and filename expansion. With default value of IFS, you got three separated words: --options, '1 and 2'.

The best way to archive this is using "$@":

#!/bin/sh

set -- --options '1 2'

./count_args "$@"
cuonglm
  • 153,898