Há um tipo especial de variável que é usado para armazenar código, isso é funções :
cmd_tmpl() { sudo -u "$USER_NAME" "$USER_HOME/script.sh" "$@"; }
cmd() { cmd_tmpl other args "$@"; }
cmd | output_processing...
As outras abordagens são para considerar as variáveis como linhas de comando (código shell) e interpretar esse código no final usando eval
:
cmd_tmpl='sudo -u "$USER_NAME" "$USER_HOME/script.sh"'
cmd=$cmd_tmpl' other args as shell code'
eval "$cmd" | output_processing...
Usar $cmd | output_processing
está errado. $cmd
é uma variável escalar e você está usando o operador split + glob para obter a lista de argumentos para um comando simples, você não está avaliando a linha de comando armazenada nela. Então, isso só funciona em um conjunto restrito de condições.
Você pode armazenar argumentos em um comando simples em uma matriz:
cmd=(sudo -u "$USER_NAME" "$USER_HOME/script.sh" ...)
"${cmd[@]}" | post_processing
mas isso não ajudará na expansão adiada de suas variáveis.
Você pode adiar a expansão com coisas como:
cmd_tmpl='sudo -u "$USER_NAME" "$USER_HOME/script.sh"'
...
eval "cmd=($cmd_tmpl)" # now expanded
cmd+=(other args)
"${cmd[@]}" | post-processing
(observe que é uma boa prática reservar nomes de variáveis com todas as letras maiúsculas para variáveis exportadas para o ambiente).