Shell – How to have a script work with “$@” or a default list of parameters while not breaking paths with whitespace

argumentsshell-script

I want a script that will run another utility over some default paths if no parameters are passed to it; ideally I want this safe for paths that contain spaces.

So far I have script.sh:

#!/bin/sh
base=$(dirname "$0")
exec touch "${@:-"$base/aaa" "$base/bbb"}"

If I put this into a folder called "foo bar" and run it as:

foo\ bar/script.sh

I want it to should end up doing:

touch foo\ bar/aaa foo\ bar/bbb

i.e. create files "aaa" and "bbb" under "foo bar", the directory in which the script is located.

Instead I get the error

touch: cannot touch 'foo bar/aaa foo bar/bbb': No such file or directory

(If I pass in parameters to the script it seems to work fine. Presumably removing the outer quotes in the last command would reverse my cases.)

Best Answer

It appears you can't set default parameters in an expansion of ${@:-...}, and "${@:-"$base/aaa" "$base/bbb"}" is expanded as a single string.

If you want to set default parameters you might want to do this:

base=$(dirname -- "$0")
# test explicitly for no parameters, and set them.
if [ "$#" -eq 0 ]; then
    set -- "$base/aaa" "$base/bbb"
fi

Then, the "$@" magically quoted parameter substitution can happen unabated:

touch -- "$@"
Related Question