I need to iterate over a variable and generate multiple arguments to be passed to a command later on in a bash script.
Example:
VAR_FILES="a.json;b.json"
IFS=';'
read -ra ADDR <<< "$VAR_FILES"
CMD_ARGS=""
for i in "${ADDR[@]}"; do
CMD_ARGS="$CMD_ARGS-var-file=$i "
done
terraform plan -input=false $CMD_ARGS -out=test.plan
I would expect the above to work with the terraform command, however the command is reading the variable as a single argument as reflected in the error message below.
user@local:~/test/$ terraform plan -input=false $CMD_ARGS -out=test.plan
╷
│ Error: Failed to read variables file
│
│ Given variables file "a.json" -var-file="b.json" does not exist.
╵
It's successfully reading the leading -var-file=
and first filename, but then reads the rest of the variable as a part of the first -var-file
argument.
CodePudding user response:
IFS=';'
changes the inter-field separator for the rest of the script, which messes up word splitting. If you prepend it to the read
call then it will only be in effect for that command.
You can also use an array to properly store multiple words and avoid word splitting altogether.
var_files="a.json;b.json"
IFS=';' read -ra addrs <<< "$var_files"
cmd_args=()
for addr in "${addrs[@]}"; do
cmd_args =(-var-file="$addr")
done
terraform plan -input=false "${cmd_args[@]}" -out=test.plan
I've also converted all the variable names to lowercase. All uppercase names are reserved for the shell. It's best to use lowercase for your own variables so as not to risk conflicting with builtin ones.
CodePudding user response:
You are changing IFS
, and not setting it back to original value:
VAR_FILES="a.json;b.json"
OLD_IFS=${IFS}
IFS=';'
read -ra ADDR <<< "$VAR_FILES"
CMD_ARGS=""
for i in "${ADDR[@]}"; do
CMD_ARGS="$CMD_ARGS-var-file=$i "
done
IFS=${OLD_IFS}
terraform plan -input=false ${CMD_ARGS} -out=test.plan