I would like to set -x temporarily in my script and then return in to the original state.
Is there a way to do it without starting new subshell? Something like
echo_was_on=.......
... ...
if $echo_was_on; then set -x; else set +x; fi
You can check the value of $-
to see the current options; if it contains an x, it was set. You can check like so:
old_setting=${-//[^x]/}
...
if [[ -n "$old_setting" ]]; then set -x; else set +x; fi
In case it's not familiar to you: the ${}
above is a Bash Substring Replacement, which takes the variable -
and replaces anything that's not an x
with nothing, leaving just the x
behind (or nothing, if there was no x)
reset_x=false
if ! [ -o xtrace ]; then
set -x
reset_x=true
fi
# do stuff
"$reset_x" && set +x
You test a shell option with the -o
test (using [
as above or with test -o
). If the xtrace
option isn't set (set +x
), then set it and set a flag to turn it off later.
In a function, you could even have set a RETURN
trap to reset the setting when the function returns:
foo () {
if ! [ -o xtrace ]; then
set -x
trap 'set +x' RETURN
fi
# rest of function body here
}
Or in a case statement
case $- in
*x* ) echo "X is set, do something here" ;;
* ) echo "x NOT set" ;;
esac
Here are re-usable functions, based on @shellter's and @glenn jackman's answers:
is_shell_attribute_set() { # attribute, like "e"
case "$-" in
*"$1"*) return 0 ;;
*) return 1 ;;
esac
}
is_shell_option_set() { # option, like "pipefail"
case "$(set -o | grep "$1")" in
*on) return 0 ;;
*) return 1 ;;
esac
}
Usage example:
set -e
if is_shell_attribute_set e; then echo "yes"; else echo "no"; fi # yes
set +e
if is_shell_attribute_set e; then echo "yes"; else echo "no"; fi # no
set -o pipefail
if is_shell_option_set pipefail; then echo "yes"; else echo "no"; fi # yes
set +o pipefail
if is_shell_option_set pipefail; then echo "yes"; else echo "no"; fi # no
Update: for Bash, test -o
is a better way to accomplish the same, see @Kusalananda's answer.
Also:
case $(set -o | grep xtrace | cut -f2) in
off) do something ;;
on) do another thing ;;
esac
This should answer exactly the question, provided your okay with the bash extension (non POSIX) and you bash version supports it.
[[ $- =~ x ]] && echo_was_on=true || echo_was_on=false