The POSIX description of set(1p) states:
-v The shell shall write its input to standard error as it is read.
Since the command to redirect stdout/stderr of the next command constitutes "input" to the shell, I'm afraid it is not possible to reset the v
option without at least outputting the command which redirects stderr itself (or using set -v
in a subshell), ie:
echo "verbose echo"
exec 2>/dev/null
set +v
echo "non verbose echo"
gives:
$ bash -v setv.bash
echo "verbose echo"
verbose echo
exec 2>/dev/null
non verbose echo
$
While fulfilling the requirements that subshells are not used and the set(1p) invocation itself is not output, this kind of redirection comes with a downside that subsequent output to stderr will also be redirected to /dev/null unless redirected again, to stdin or such.
The x
option to set(1p) is a special case. It is worth noting, that the POSIX states the following:
-x
The shell shall write to standard error a trace for each command after it expands the command and before it executes it. It is unspecified whether the command that turns tracing off is traced.
while the GNU Bash Manual states:
-x
Print a trace of simple commands, for commands, case commands, select commands, and arithmetic for commands and their arguments or associated word lists after they are expanded and before they are executed. The value of the PS4 variable is expanded and the resultant value is printed before the command and its expanded arguments.
As an aside, with a replacement of &>
by 2>
, dash (a shell whose design goal is strict POSIX compliance) follows this behavior of Bash and suppresses the output of { set +x; } 2>/dev/null
, while for example mksh doesn't:
$ cat setx.sh
echo "verbose echo"
{ set +x; } 2>/dev/null
echo "non verbose echo" >&2
$ dash -x setx.sh
+ echo verbose echo
verbose echo
non verbose echo
$ mksh -x setx.sh
+ echo 'verbose echo'
verbose echo
+ 2>/dev/null
+ set +x
non verbose echo
set -v
active, each line of the script is outputted when the shell reads it. It has nothing to do with executing the lines. The-x
and-v
shell options are very different in this regard. You are asking for a way of getting the shell to not output the line that contains theset +v
command, when it reads that line. AFAIK, that is impossible as the line has not yet been executed.verbose
is enabled?v
in set(1p) (quoted in my answer below). The wording it uses is "input", which includes comments.