Shell Script: creating a variable with options inside
Putting a complex command in a variable is a never a recommended approach. See BashFAQ/050 - I'm trying to put a command in a variable, but the complex cases always fail!
Your requirement becomes really simple, if you just decide to use a function instead of a variable and pass arguments to it.
Something like
rsync_custom() {
[ "$#" -eq 0 ] && { printf 'no arguments supplied' >&2; exit 1 ; }
rsync -avz --{partial,stats,delete,exclude=".*"} "$@"
}
and now pass the required arguments to it as
rsync_custom /dir1 /dir2
The function definition is quite simple in a way, we first check the input argument count using the variable $#
which shouldn't be zero. We throw a error message saying that no arguments are supplied. If there are valid arguments, then "$@"
represents the actual arguments supplied to the function.
If this is a function you would be using pretty frequently i.e. in scripts/command-line also, add it to the shell startup-files, .bashrc
, .bash_profile
for instance.
Or as noted, it may be worthwhile to expand the brace expansion to separate args for a better readability as
rsync_custom() {
[ "$#" -eq 0 ] && { printf 'no arguments supplied' >&2; exit 1 ; }
rsync -avz --partial --stats --delete --exclude=".*" "$@"
}
VAR=rsync -avz --{partial,stats,delete,exclude=".*"}
This tries to run the command -avz
with arguments --partial
, --stats
etc.. and with VAR
set to rsync
in the environment.
VAR='rsync -avz --{partial,stats,delete,exclude=".*"}'
The quoted form doesn't work because braces aren't expanded in quotes, and not inside assigments, and neither are they expanded after a variable is expanded.
If you need to store command line arguments in a variable, use an array:
args=(rsync -avz --{partial,stats,delete,exclude=".*"})
Now "${args[@]}"
will expand to rsync
, -avz
, --partial
, etc. as distinct words.
Arrays also allow you to append options to the list, conditionally if need be, so you can e.g.:
args=(this that)
if something ; then
args+=(another_arg)
fi
"$cmd" "${args[@]}"