I want to define a variable in a script that will be used as extra arguments for a command.
For this question I will use ls
, but my real-world usecase is an rsync command with --rsync-path="docker run ..."
.
set -x
# Set extra arguments.
export LS_ARGS_OVERRIDE='-a --color="hello world"'
# Call `ls` with extra arguments
ls "${LS_ARGS_OVERRIDE}" -l .
Expected result is
+ ls -a --color="hello world" -l .
ls: unsupported --color value 'hello world' (must be always, auto, or never)
I tried the naive way:
echo
echo "Direct usage quoted"
ls "${LS_ARGS_OVERRIDE}" -l .
echo
echo "Direct usage unquoted"
ls ${LS_ARGS_OVERRIDE} -l .
Which resulted in
Direct usage quoted
+ ls '-a --color="hello world"' -l .
ls: invalid option --
usage: ls [-@ABCFGHILOPRSTUWabcdefghiklmnopqrstuvwxy1%,] [--color=when] [-D format] [file ...]
Direct usage unquoted
+ ls -a '--color="hello' 'world"' -l .
ls: unsupported --color value '"hello' (must be always, auto, or never)
I then tried using arrays as suggested on this stackoverflow
echo
echo "Input quoted"
MY_LOCAL_VAR=("${LS_ARGS_OVERRIDE:-}")
ls ${MY_LOCAL_VAR[@]} -l .
echo
echo "Everything quoted"
MY_LOCAL_VAR=("${LS_ARGS_OVERRIDE:-}")
ls "${MY_LOCAL_VAR[@]}" -l .
echo
echo "Arguments quoted"
MY_LOCAL_VAR=(${LS_ARGS_OVERRIDE:-})
ls "${MY_LOCAL_VAR[@]}" -l .
echo
echo "Nothing quoted"
MY_LOCAL_VAR=(${LS_ARGS_OVERRIDE:-})
ls "${MY_LOCAL_VAR[@]}" -l .
Which outputs
Input quoted
+ ls -a '--color="hello' 'world"' -l .
ls: unsupported --color value '"hello' (must be always, auto, or never)
Everything quoted
+ ls '-a --color="hello world"' -l .
ls: invalid option --
usage: ls \[-@ABCFGHILOPRSTUWabcdefghiklmnopqrstuvwxy1%,\] \[--color=when\] \[-D format\] \[file ...\]
Arguments quoted
+ ls -a '--color="hello' 'world"' -l .
ls: unsupported --color value '"hello' (must be always, auto, or never)
Nothing quoted
+ ls -a '--color="hello' 'world"' -l .
ls: unsupported --color value '"hello' (must be always, auto, or never)
I finally tried to pass flags after the argument as suggested in this stackoverflow
echo
echo "arguments after"
ls . "${MY_LOCAL_VAR[@]}" -l
To get
Use arguments after
+ ls . '-a --color="hello world"' -l
ls: -a --color="hello world": No such file or directory
ls: -l: No such file or directory
.:
README.markdown
But none of this worked.
Edit 2023 June 20th
The reason I did not use array directly is that LS_ARGS_OVERRIDE
is defined in another file.
Let's say There is 2 scripts, A and B, where A define arguments and then calls B:
# Script A
LS_ARGS_OVERRIDE=(-a --color="hello world")
./B
Then B calls the command with args
# script B
ls "${LS_ARGS_OVERRIDE[@]}" -l .
In this configuration, LS_ARGS_OVERRIDE
appears alway empty in script B, while using a string makes it available in B.