So I'm writing a shell-script that takes optional arguments (parsing them with getopts
and what not; but that doesn't really matter here).
The user (of the script) is supposed to pass some paths as arguments, which are then processed by some workhorse utilitiy.
Of course the paths may contain spaces, so I'm passing the args on with double-quotes ("$@"
), along with numerous other flags:
something like this:
workhorse \
--verbose \
--stats \
--one-flag \
--another-flag \
"$@"
Everything works nicely, but then:
If the user did not specify any paths, I would like to fall back to some default values. I have no idea how to achieve this while still be able to handle spaces and what not.
the naive approach would be something like:
if [ $# -gt 0 ]; then
workhorse \
--verbose \
--stats \
--one-flag \
--another-flag \
"$@"
else
workhorse \
--verbose \
--stats \
--one-flag \
--another-flag \
/home/foo /home/bar
fi
But that of course is very ugly.
Instead, I would like to use variable substitution, to replace the $@
with default values, like so:
default_paths="/home/foo /home/bar"
workhorse \
--verbose \
--stats \
--one-flag \
--another-flag \
${@:-${default_paths}}
This works, as long as the paths passed via the cmdline do not contain any whitespace (no double quotes around $@
).
To support whitespaces in the args, I would use double-quote but "${@:-${default_paths}"
will (while correctly expanding the cmdline-args) pass the /home/foo /home/bar
string as a single argument to my workhorse.
I could simplify my "ugly" solution above (that just calls the workhorse differently, depending on whether there are any cmdline-provided paths or nor), by putting the flags into a $flags
variable - but what if those flags could contain (paths with) spaces themselves?
So: is there a way to provide default values for variadic shell arguments that can contain spaces?
Something like the inverse of shift
might help (where you push new arguments to positional parameters queue)
I'm looking for a POSIX-compliant solution (rather than bash-arrays).
If you have control over how default_paths
gets set in your script, then you can just use set
to assign the paths as positional arguments
if [ $# -eq 0 ]; then
set -- "/home/foo" "/home/bar" "/home/path with spaces"
fi
and continue using "$@"
as the arguments list.