Reputation: 12868
I am enabling echoing of commands in a bash script using "set -x". When I turn off echoing, I am issuing "set +x" but I don't want that command echo'd. To do this, I issue the command:
{ set +x; } 2>/dev/null
This works fine. However, I'm not completely understanding why this works and the following does not:
set +x 2>/dev/null
Obviously the echoing of the command doesn't go to stderr, but I'm not really understanding why the command with the semicolon in the curly braces works.
Upvotes: 5
Views: 2215
Reputation: 295472
The reason you need to use braces is that xtrace
logging (the + set +x
line you're trying to suppress) is not output from the command set +x
itself (a command which, on its own, writes nothing to either stderr or stdout). Instead, it's output from the shell invoking set +x
.
When you run set +x 2>/dev/null
, that redirects stderr to /dev/null
only for the execution of set +x
itself. It does not redirect things the shell does while setting up to run that command, which includes printing trace logs.
By contrast, when you run { set +x; } 2>/dev/null
, that does the redirection before running the entire block of code, which includes by nature pre-command setup for each command within that block. Thus, the setup for the command is run in the redirected environment as well.
You wouldn't want it to be otherwise -- what use would set -x
be if someprogram 2>/dev/null
didn't log that it had invoked someprogram
at all?
Incidentally, this is very similar to why the shell-builtin time
command's output is not subject to redirection unless wrapped in a larger context; for more on that, see BashFAQ #32.
Upvotes: 10