What is the difference between shell options -v and -x for debugging?
Asked Answered
A

2

8

-x means xtrace and -v means verbose.

When researching, I find that bash -x "expands commands" while -v prints out the entire command to stdout before execution.

The only difference I see when testing this is that bash -v <scriptname> will display comments of each command as well.

Is this really the only difference? Can someone elaborate?

Accessary answered 14/11, 2016 at 3:14 Comment(2)
Why the downvote?Accessary
I have not voted. See: help set | grep '^ *-[xv]'Soult
I
8

From the manual:

  -v  Print shell input lines as they are read.
  -x  Print commands and their arguments as they are executed.

You can see this distinction when looking at how piped commands are handled:

$ set -v
$ echo "Hello World" | sed 's/World/Earth/'
echo "Hello World" | sed 's/World/Earth/'
Hello Earth

versus:

$ set -x
$ echo "Hello World" | sed 's/World/Earth/'
    + sed s/World/Earth/
    + echo 'Hello World'
    Hello Earth

Also, it appears that xtrace (-x) uses the $PS4 variable, while verbose (-v) does not.

Imitation answered 14/5, 2018 at 2:2 Comment(0)
K
1

The outputs are very similar for simple commands, but it seems that set -v (verbose) simply repeats the input line, while set -x (xtrace) shows the command(s) that are run after variable expansions and word splitting, etc. Considering the examples below, it seems to me that it's worth using both when debugging shell scripts: verbose helps navigate the script and show the intention of the commands, while xtrace shows in more detail what is actually being run. I'm going to use set -vx when debugging scripts from now on. The differences become more obvious in examples with variables, command lists, functions, etc:

$ set +vx           # both disabled (default for most people)
$ foo=(1 2 '3 three')
$ printf 'foo is %s\n' "${foo[@]}" && echo ''
foo is 1
foo is 2
foo is 3 three

$ set -v            # verbose
$ printf 'foo is %s\n' "${foo[@]}" && echo ''
printf 'foo is %s\n' "${foo[@]}" && echo ''
foo is 1
foo is 2
foo is 3 three

$ set +v
set +v
$ set -x            # xtrace
$ printf 'foo is %s\n' "${foo[@]}" && echo ''
+ printf 'foo is %s\n' 1 2 '3 three'
foo is 1
foo is 2
foo is 3 three
+ echo ''

$ set +x
+ set +x
$ set -vx           # both verbose and xtrace
$ printf 'foo is %s\n' "${foo[@]}" && echo ''
printf 'foo is %s\n' "${foo[@]}" && echo ''  # from verbose, input line simply repeated
+ printf 'foo is %s\n' 1 2 '3 three'         # from xtrace, command list split, variables substituted
foo is 1
foo is 2
foo is 3 three
+ echo ''

# word splitting behaviour is made more obvious by xtrace
# (note the array is unquoted now)
$ printf 'foo is %s\n' ${foo[@]} && echo ''
printf 'foo is %s\n' ${foo[@]} && echo ''
+ printf 'foo is %s\n' 1 2 3 three           # missing single quotes due to word splitting
foo is 1
foo is 2
foo is 3
foo is three                                 # !
+ echo ''

# function with both verbose and xtrace set
$ function bar { printf '%s\n' "${foo[@]}"; }
function bar { printf '%s\n' "${foo[@]}"; }  # verbose repeats definition, nothing output by xtrace
$ bar
bar                                          # verbose repeats function call
+ bar                                        # xtrace shows commands run
+ printf '%s\n' 1 2 '3 three'
1
2
3 three

Aside: other shells

The above examples are from bash. In my testing, the output of posix dash for both options is very similar, although of course no arrays are possible in that shell. zsh expands the xtrace output slightly by prepending with a line number, but otherwise behaves very similarly (although here, its different word splitting behaviour is apparent):

$ zsh
% foo=(1 2 '3 three')
% set -vx
% printf 'foo is %s\n' ${foo[@]} && echo ''
printf 'foo is %s\n' ${foo[@]} && echo ''    # verbose repeats input command
+zsh:14> printf 'foo is %s\n' 1 2 '3 three'  # xtrace prints expanded command with line number
foo is 1
foo is 2
foo is 3 three
+zsh:14> echo ''

Kiosk answered 6/7, 2022 at 17:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.