How many times have you seen someone trying to “Log the command I run and the output of the command”? It happens often, and for seeing the command you’re running set -v is nice, (set -x is nice, too, but it can be harder to read), but what happens when you want to capture the command being run… but not all commands being run?
Running interactively I don’t see a way to capture the set -v output at all.
set -v
echo a 1>/dev/null # 'echo a 1>/dev/null' is printed to the screen
echo a 2>/dev/null # 'echo a 2>/dev/null\na' is printed to the screen
I can put this in a script and things get better:
echo 'set -v'$'\n''echo a' > setvtest.sh
bash setvtest.sh 1>/dev/null # 'echo a' is printed to the screen
bash setvtest.sh 2>/dev/null # 'a' is printed to the screen
Aha, so from a script it goes to stderr. What about inline?
set +v
{ set -v ; echo a ; } 1>/dev/null # no output
set +v
( set -v ; echo a ; ) 1>/dev/null # no output
Hmm, no luck there.
Interestingly, and as a side note, this produces no output:
echo 'set -v ; echo a' > setvtest.sh
bash setvtest.sh 1>/dev/null
I’m not sure why, but perhaps that’s also why the subshell version returns nothing.
What about shell functions?
setvtest2 () {
set -v
echo a
}
setvtest2 # 'a'
set +v
setvtest2 1>/dev/null # nothing
set +v
setvtest2 2>/dev/null # nothing
Now the question: Is there a nice way to capture the output of set -v?
Here’s my not-nice hack, so I’m looking for something less insane:
#!/usr/bin/env bash
script=/tmp/$$.script
output=/tmp/$$.out
echo 'set -v'$'\n'"$1" >"$script"
bash "$script" 1>"$output"
cat "$output"
rm -f "$script" "$output"
Now I can execute simple scripts
bash gen.sh 'echo a' 1>/dev/null # prints 'echo a'
bash gen.sh 'echo a' 2>/dev/null # prints 'a'
But surely there are better ways.
You can run bash with option
-vinstead of turning on and off viaset:The dark side of this solution is that each such line will require to create new bash process, but you will not have to remember to switch off the
voption back, since it’s switched on only in a child process.