I want to set -x at the beginning of my script and undo it (go back to the state before I set it) afterward instead of blindly setting +x. Is this possible?P.S.: I've already checked here; that didn't seem to answer my question as far as I could tell.
How to undo a `set -x`?
bash;shell
This command:shopt -po xtracewill generate an executable string that reflects the state of the option.The p flag means print, and the o flag specifiesthat we are asking about option(s) set by the set command(as opposed to option(s) set by the shopt command).You can assign this string to a variable, and execute the variable at the end of your script to restore the initial state.# store state of xtrace option.tracestate=$(shopt -po xtrace)# change xtrace as neededecho some commands with xtrace as externally selectedset -xecho some commands with xtrace set# restore the value of xtrace to its original value.eval $tracestateThis solution works for multiple options simultaneously:oldstate=$(shopt -po xtrace noglob errexit)# change options as neededset -xset +xset -fset -eset -x# restore to recorded state:set +vx; eval $oldstateAdding set +vx avoids the printing of a long list of options.And, if you dont list any option names,oldstate=$(shopt -po)it gives you the values of all options.And, if you leave out the o flag,you can do the same things with shopt options:# store state of dotglob option.dglobstate=$(shopt -p dotglob)# store state of all options.oldstate=$(shopt -p)If you need to test whether a set option is set,the most idiomatic (Bash) way to do it is:[[ -o xtrace ]]which is better than the other two similar tests:[[ $- =~ x ]][[ $- == *x* ]]With any of the tests, this works:# record the state of the xtrace option in ts (tracestate):[ -o xtrace ] && ts='set -x' || ts='set +x'# change xtrace as neededecho some commands with xtrace as externally selectedset -xecho some commands with xtrace set# set the xtrace option back to what it was.eval $tsHeres how to test the state of a shopt option:if shopt -q dotglobthen        # dotglob is set, so echo .* * would list the dot files twice.        echo *else        # dotglob is not set.  Warning: the below will list . and ...        echo .* *fiPOSIXA simple, POSIX-compliant solution to store all set options is:set +owhich is described in the POSIX standard as:+o  Write the current option settings to standard output in a format  that is suitable for reinput to theshell  as commands that achieve the same options settings.So, simply:oldstate=$(set +o)will preserve values for all options set using the set command.Again, restoring the options to their original values is a matter of executing the variable:set +vx; eval $oldstateThis is exactly equivalent to using Bash's shopt -po. Note that it will not cover all possible Bash options, as some of those are set by shopt.For Bash, this will store all of the possible options:oldstate=$(shopt -po; shopt -p)set +vx; eval $oldstate             # use to restore all options.Note: each shell has a slightly different wayto build the list of options that are set or unset(not to mention different options that are defined),so the strings are not portable between shells,but are valid for the same shell.zsh special casezsh also works correctly (following POSIX) since version 5.3. In previous versions it followed POSIX only partially with set +o in that it printed options in a format that was suitable for reinput to the shell as commands, but only for set options (it didn't print un-set options).