I am storing a command to execute in a bash array, example:
declare -a cmd=("sudo" "dnf" "update")
"${cmd[@]}"
Last metadata expiration check: 0:24:45 ago on Fri 07 Jan 2022 03:35:34 PM EST.
Dependencies resolved.
Nothing to do.
Complete!
Now, say I want to redirect the output to make it less noisy. This works:
"${cmd[@]}" &>/dev/null
But I would prefer to store the redirect with the command array so it can be added/removed like any other command in the array:
declare -a cmd=("sudo" "dnf" "update" "&>/dev/null")
"${cmd[@]}"
Last metadata expiration check: 0:29:14 ago on Fri 07 Jan 2022 03:35:34 PM EST.
No match for argument: &>/dev/null
The output isn't being redirected, the final array element is just being passed like a normal argument. Is there any way to get this work (i.e. judicious use of eval) or a better strategy?
XY statement: I am trying to use conditionals to make my program output silent. I can do this with:
silent=true
cmd=("sudo" "dnf" "update")
if silent; then
"${cmd[@]}" &>/dev/null
else # Be noisy
"${cmd[@]}"
fi
This results in lots of duplicated code over the course of my program (every debug operation needs multiple command execution lines). Instead I would prefer appending the redirection to the array, such as:
silent=true
cmd=("sudo" "dnf" "update")
$silent && cmd =("&>/dev/null")
"${cmd[@]}"
This strategy works great for functions and arguments but not for redirections. While I can apply --quiet flags to some programs to achieve this, in some cases I would like to redirect stderr, redirect to file, etc.
CodePudding user response:
You have to use eval to process shell operations in the variable expansion.
declare -a cmd=("sudo" "dnf" "update" "&>/dev/null")
eval "${cmd[@]}"
CodePudding user response:
If you want to avoid duplicate "${cmd[@]}" code, you can use a subshell:
(
[[ $silent == true ]] && exec &>/dev/null
exec "${cmd[@]}"
)
I suggest the use of exec if cmd will always be an external command.
