I have a very basic function.
t() {
[[ -f ./terragrunt.hcl ]] && local exe=terragrunt
[[ ! -f ./terragrunt.hcl ]] && local exe=terraform
[[ ! $exe ]] && echo -e "\033[31;1m[ERROR]\033[0m Can't figure out what to run. Please run manually"
local cmd="$exe $@"
[[ $DEBUG ]] && echo -e "\033[34;1m[DEBUG]\033[0m executable is $exe.
Args are $@
Command to be run: $cmd"
$cmd
}
However, when I run it like t outputs
It returns t:9: command not found: terraform output
I can run terraform output
and get the proper output.
I have tried eval
and return
as well, neither work.
CodePudding user response:
Don't use cmd
at all; there's no good way to correctly encode a valid command line in a single string.
t() {
[[ -f ./terragrunt.hcl ]] && local exe=terragrunt
[[ ! -f ./terragrunt.hcl ]] && local exe=terraform
[[ ! $exe ]] && echo -e "\033[31;1m[ERROR]\033[0m Can't figure out what to run. Please run manually"
[[ $DEBUG ]] && echo -e "\033[34;1m[DEBUG]\033[0m executable is $exe.
Args are $@
Command to be run: $exe $@"
"$exe" "$@"
}
Constructing an accurate string representation of the command resulting from an arbitrary value of $@
is non-trivial and barely worth doing.
CodePudding user response:
The problem is that you're doing:
local cmd="$exe $@"
This constucts a single string out of $exe
and $@
, and when you use $cmd
it will try to run that string as a command, including spaces, as if you had typed "terraform output"
(which will try to look up /bin/terraform output
) rather than terraform output
. Hence your error:
t:9: command not found: terraform output
The easiest way to deal with this in zsh is to use arrays:
local cmd=($exe $@)
$cmd
CodePudding user response:
Word splitting occurs before parameter expansion in zsh. In your case, you would have to use
${(z)cmd}
to tell zsh that you want to have an extra round of word splitting after the expansion. However, this will word-split everything inside cmd
. I you want to avoid this, make cmd
an array , where the command itself is the first element and each subsequent element is a an argument, and invoke it as
$cmd[@]