Is there a way to show the output of a command substitution, in color, while it is executing, while still storing it to a variable? This would mainly be for testing/debugging purposes, and the output would not be shown normally.
If I do this:
output=$(some_command)
if [ "$debug" ]; then
echo "$output"
fi
...then this is close, but not what I want in a few ways:
How can I conditionally stream output to a terminal without squelching color?
To store a command's results to a variable as well as streaming its output to the console:
var=$(some_command | tee /dev/stderr)
If you want to force your command to think it's outputting directly to a TTY, and thus to enable color output if it would do so when not in a pipeline, use the tool unbuffer
, shipped with expect
:
var=$(unbuffer some_command | tee /dev/stderr)
All that said: If you only want to show debugging conditionally for a long script, it makes sense to put that conditional up front at the top of your script rather than scattering it around everywhere. For instance:
# put this once at the top of your script
set -o pipefail
if [[ $debug ]]; then
exec 3>/dev/stderr
else
exec 3>/dev/null
fi
# define a function that prepends unbuffer only if debugging is enabled
maybe_unbuffer() {
if [[ $debug ]]; then
unbuffer "$@"
else
"$@"
fi
}
# if debugging is enabled, pipe through tee; otherwise, use cat
capture() {
if [[ $debug ]]; then
tee >(cat >&3)
else
cat
fi
}
# ...and thereafter, when you want to hide a command's output unless debug is enabled:
some_command >&3
# ...or, to capture its output while still logging to stderr without squelching color...
var=$(maybe_unbuffer some_command | capture)