What is the meaning of number of plus+ sign in stderr in bash when "set -x"

In Bash, you can see

set --help

  -x  Print commands and their arguments as they are executed.

Here’s test code:

# make script
echo '
    #!/bin/bash
    set -x
    n=$(echo "a" | wc -c)
    for i in $(seq $n)
    do
        file=test_$i.txt
        eval "ls -l | head -$i"> $file
        rm $file
    done
' > test.sh
# execute
chmod +x test.sh
./test.sh 2> stderr
# check
cat stderr

Output

+++ echo a
+++ wc -c
++ n=2
+++ seq 2
++ for i in $(seq $n)
++ file=test_1.txt
++ eval 'ls -l | head -1'
+++ ls -l
+++ head -1
++ rm test_1.txt
++ for i in $(seq $n)
++ file=test_2.txt
++ eval 'ls -l | head -2'
+++ ls -l
+++ head -2
++ rm test_2.txt

What is the meaning of the number of + signs at the beginning of each row in the file? It’s kind of obvious, but I want to avoid misinterpreting.
In addition, can a single + sign appear there? If so, what is the meaning of it?

>Solution :

The number of + represents subshell nesting depth.

Note that the entire test.sh script is being run in a subshell because it doesn’t begin with #!/bin/bash. This has to be on the first line of the script, but it’s on the second line because you have a newline at the beginning of the echo argument that contains the script.

When a script is run this way, it’s executed by the original shell in a subshell, approximately like

( source test.sh )

Change that to

echo '#!/bin/bash
    set -x
    n=$(echo "a" | wc -c)
    for i in $(seq $n)
    do
        file=test_$i.txt
        eval "ls -l | head -$i"> $file
        rm $file
    done
' > test.sh

and the top-level commands being run in the script will have a single +.

So for example the command

n=$(echo "a" | wc -c)

produces the output

++ echo a
++ wc -c
+ n='       2'

echo a and wc -c are executed in the subshell created for the command substitution, so they get two +, while n=<result> is executed in the original shell with a single +.

Leave a Reply