Você deve usar "${@}" em vez de ${@} (como com echo "${@}" ), mas essa não é a razão do seu problema.
O motivo é que o redirecionamento ocorre muito cedo na análise da linha de comando, antes da substituição do parâmetro. Assim, depois que a variável colocar > na linha de comando, o shell não está mais procurando > .
Um ponto importante que notei depois de publicar minha resposta: com uma chamada como
run mysqldump blabla > dump.sql
a função run não vê > e dump.sql . Isso provavelmente não é o que você deseja porque impede que você altere todos os redirecionamentos com uma única variável de ambiente, já que a saída de echo "${@}" é redirecionada para o arquivo também. Assim, você deve usar algo como run --redirect dump.sql mysqldump blabla , veja abaixo.
Existem duas possibilidades:
-
Cole com
"$@"e useeval. Isso pode levá-lo a um pesadelo de citação, é claro. Você precisa citar tudo, exceto o>, para que o shell veja um>na linha de comando antes de fazer a remoção da cotação. -
Manipule o redirecionamento separadamente:
run --redirect dump.sql mysqldump blabla run() { if [ "$1" == '--redirect' ]; then shift redirect_target="$1" shift else redirect_target='/dev/stdout' # works at least with Linux fi if [[ "$(printenv DRY_RUN)" = "yes" ]] then echo "${@}" else "${@}" > "$redirect_target" fi }Você pode evitar o
redirect_target='/dev/stdout'se você colocar oif [ "$1" == '--redirect' ]na filialelsedeif [[ "$(printenv DRY_RUN)" = "yes" ]].if [[ "$(printenv DRY_RUN)" = "yes" ]] then if [ "$1" == '--redirect' ]; then # do not output "--redirect file" shift shift fi echo "${@}" else if [ "$1" == '--redirect' ]; then shift redirect_target="$1" shift "${@}" > "$redirect_target" else "${@}" fi fi