Hello, that came up when discussing a related bug in zsh (http://www.zsh.org/mla/workers/2016/msg01574.html)
$SHLVL is a feature introduced by tcsh (at least some patches on tcsh) in the early eighties, that is meant to represent the depth of a stack of shells executing each other. It's not POSIX, but it's supported by tcsh, bash, zsh, ksh93 and busybox sh at least. It's not incremented for subshells, only for shell invocations. Where the behaviour differs is when using "exec". All of tcsh, bash and zsh (but not ksh93 nor busybox sh) decrement SHLVL when a "exec" would replace the shell process with another command. That makes sense because in bash(1) | `- bash(2) | `- bash(3) -c 'exec bash(4)' for instance, that bash(4) will end up being the child of bash(2), just like bash(3). So bash(3) decrements SHLVL before invoking bash(4), which will increment it again. Now, and it's my first bug. In: $ echo "$SHLVL $$" 2 6192 $ bash -c bash $ echo "$SHLVL $$ $PPID" 4 6193 6192 SHLVL has been increased by *2* even though that new bash shell is a direct child of the previous one. That's because that "bash -c bash" is actually a "bash -c 'exec bash'". That is bash optimises out the fork for the execution of that one command. While SHLVL is decremented for an explicit "exec", it is not for an implicit one which IMO is a bug Second bug: $ SHLVL=1 bash -c 'echo "$SHLVL"; (exec bash); echo done' 2 $ echo "$SHLVL" 2 $ exit done There, bash has decremented $SHLVL upon "exec bash" even though it was in a subshell. So the new bash shell ended up with the same SHLVL as its parent. tcsh has the same bug. (tested with the head of the "devel" git branch) -- Stephane