Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Is it possible to test whether a bash script was executed with -x?

I'm writing a script which also runs some remote scripts, and I'd like to be able to do something like:

USE_X="$( run_with_x && "-x" || "" )"
ssh $host "bash $USE_X some_script.sh"
share|improve this question
up vote 8 down vote accepted

Just look at the $- variable.

USE_X=`case "$-" in *x*) echo "-x" ;; esac`

(Yup, I did manage to do that without invoking grep. Save the pids!)

share|improve this answer
what does *x* expand to? – bbaja42 Oct 3 '11 at 6:55
What a waste of pid! case $- in *x*) USE_X="-x";; *) USE_X=;; esac @bbaja42 It doesn't expand to anything: it's a pattern that the string $- is matched against. – Gilles Oct 3 '11 at 21:08
@Gilles Your example also contains unnecessary part: *) USE_X=;; changes nothing, if USE_X was not set previously. Also, the whole case construct is unnecessary (see my version - isn't that simpler?) – rozcietrzewiacz Oct 4 '11 at 16:12
@rozcietrzewiacz This part is unnecessary if USE_X has been initialized earlier on. I don't consider your version simpler: it's a few characters shorter (and even then only if USE_X has been initialized, otherwise it's longer), but at the expense of clarity and portability. – Gilles Oct 4 '11 at 17:11
@Gilles Portability is not the subject of this question, it is about bash. Initializing USE_X is not necessary for the purpose of OP's intended use (to pass $USE_X to further scripts). Using case construct looks less clear and natural than a regular condition evaluation in my view. – rozcietrzewiacz Oct 4 '11 at 17:53

After reading man pages and grepping for things, here's the solution:

$ cat show_x.sh
if [ "$(set | grep xtrace)" ]; then
    echo "xtrace is on. :D"
    echo "xtrace is off. :("


$ bash show_x.sh 
xtrace is off. :(

$ bash -x show_x.sh 
++ set
++ grep xtrace
+ '[' SHELLOPTS=braceexpand:hashall:interactive-comments:xtrace ']'
+ echo 'xtrace is on. :D'
xtrace is on. :D
share|improve this answer

Probably the simplest way of parsing $-, similar to dagbrown's method (also pure bash), but without using case and backticks (subshell):

if  [[ ${-/x} != $- ]] ; then USE_X="-x"; fi

or even shorter:

[[ ${-/x} != $- ]] && USE_X="-x"

Note that [[ is not an invocation of test builtin program (as is the case with [), but a bash syntax construct (according to man bash and this dev recommendation). So I claim it to be "purer bash" ;)

share|improve this answer
Nice solution. I suggest tagging '|| USE_X="+x"' on the end of the second expression so you may then call 'set "$USE_X"' and it will work to restore the initial setting whether or not xtrace was set. – Binary Phile Dec 23 '14 at 15:14

The bash man page documents set -o xtrace as equivalent to set -x, which in turn is equivalent to giving -x as an argument to the shell. (So far, this is compatible with SUSv3 sh, with the caveat that -o option is required "if the system supports the User Portability Utilities option".)

Also, set -o without an option prints the current status of all of the -o options. (SUSv3 specifies this as well, but not usefully; the format is unspecified, so you can only depend on it if you know you're running a shell that uses a format similar to bash's.)

So, the pipeline set -o | grep xtrace | grep -q on should be what you're looking for.

share|improve this answer

This expression will be true if the script is run with -x, false otherwise: [[ $- =~ x ]] So this expression will be "-x" if the script is run with -x and "" (empty) otherwise: $([[ $- =~ x ]] && echo "-x")

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.