Is there a way for a script to log both, the command line run (including piped ones) plus its output without duplicating the line for the command?
The intention is that the script should have a clean output, but should log verbosely into a log file (so no set -x). Apart from the output, it shall also log the command line causing the output, which could be a piped command-one liner.
The most basic approach is to duplicate the command line in the script and then dump it into the log followed by the captured output of the actual command being run:
echo "command argument1 \"quoted argument2\" | grep -oE \"some output\"" >> file.log
output="$(command argument1 "quoted argument2" 2>&1 | grep -oE "some output")"
echo "${output}" >> file.log
This has the side effect that quoted sections would need to be escaped for the log, which can lead to errors resulting in confusion.
If none of the commands were piped, one could store the command line in an array and then "run" the array.
command=(command argument1 "quoted argument2")
echo "${command[@]}" >> file.log
output="$("${command[@]}" 2>&1)"
echo "${output}" >> file.log
Though with this approach "quoted argument2" would become quoted argument2 in the log.
Is there a way (in bash) to realize this without having to duplicate the commands?
eval? Something likecmd="..."; echo "$cmd" &>> file.log; eval "$cmd" &>> file.log.evalis still a mystery to me on what it does. So, I usually use it sparsely as I prefer to understand a tool before using it extensively. I can surely tinker with it and give it a try. Will report back if that solves what I intend to do. Thanks!eval, however. Its use for this case is probably not the best idea. By the way, why turning the-xoption on and off on demand is not an option?-x, it would pump out everything to STDOUT to my understanding. This would no longer provide a clean output to the user. Though I have not tried running it inside a command substitution where the output is captured in a variable. However, apart from outputting the commands and results, which is what I actually want, it will also introduce new characters (namely "+") at the beginning of each line as well as itself (+ set +x) when disabling it again. If possible, I would like to avoid that.-xon before the command you are interested in, and off just after. And unsetingPS4suppresses the+. SoPS4=; set -x; <your command>; set+xshould do almost what you want (except for theset +xthat will be logged too). Of course, you'll have to redirect everything else elsewhere with someexec <redirection>commands.