2

I have a shell script that runs exec to replace itself with another command. The other command takes some optional arguments.

exec mycommand $ARG1 $ARG2 $ARG3

Any of these arguments could be populated or not populated. If they aren't populated, they don't render as an argument to the function. For example:

# if you have:
ARG1=foo
ARG3=bar
exec mycommand $ARG1 $ARG2 $ARG3
# then you get:
exec mycommand foo bar

However, I want spaces to be legal in the values for these arguments, and for this not to cause them to produce additional arguments. That is,

# if you have
ARG1="foo bar baz"
ARG2="qux"
exec mycommand $ARG1 $ARG2 $ARG3
# then I want:
exec mycommand "foo bar baz" qux
# not:
exec mycommand foo bar baz qux

I tried putting escaped quotes into the arguments, but exec expected them to literally be part of the value.

ARG1="\"foo bar baz\""
exec mycommand $ARG1 $ARG2 $ARG3
# gives you:
exec mycommand \"foo bar baz\"

I also tried quoting the variables in exec, but then it started passing empty strings when arguments weren't present:

ARG2="foo bar"
exec mycommand "$ARG1" "$ARG2" "$ARG3"
# gives you:
exec mycommand "" "foo bar" ""

Is there a better way to construct a command and pass it to exec? Is there another way to replace the current process with another one?

1 Answers1

1

With bash, you use an array, and all variables must be properly quoted:

ARG1="foo bar baz"
ARG3="qux"

cmd=( mycmd )

[[ -n "$ARG1" ]] && cmd+=( "$ARG1" )
[[ -n "$ARG2" ]] && cmd+=( "$ARG2" )
[[ -n "$ARG3" ]] && cmd+=( "$ARG3" )

printf "%s\n" "${cmd[@]}"
#exec "${cmd[@]}"

This will give you the invocation you want: exec mycommand "foo bar baz" qux with no "empty string" arguments. Remove the printf line and uncomment the exec line if you're happy with how it's working.

glenn jackman
  • 27,524