Vamos simplificar isso um pouco:
$ SHLVL=1 zsh -c 'echo $SHLVL; zsh -c "echo \$SHLVL"'
2
2
$ SHLVL=1 zsh -c 'echo $SHLVL; zsh -c "echo \$SHLVL"; true'
2
3
O que está acontecendo é que, se o último comando for um comando externo, o zsh o executa sem bifurcar - uma otimização de chamada final. Você pode observar isso fazendo eco de $$
além de SHLVL
: no primeiro caso, a invocação aninhada de zsh tem o mesmo PID; no segundo caso, a chamada aninhada é executada como um processo filho porque o pai permanece para executar true
posteriormente.
Você está vendo um comportamento diferente com sh
porque se comporta de maneira diferente. Talvez seu sh
seja bash, que não realiza nenhuma otimização de chamada final. Ou talvez seja o ksh93, que realiza a otimização da chamada final, mas incrementa SHLVL
, mesmo nesse caso.
O incremento de zsh deve ser de SHLVL
em uma chamada final? Não há um padrão oficial para isso, mas faria sentido, já que as chamadas finais deveriam ser uma otimização e, além das disposições do processo, eu esperaria que o comportamento fosse o mesmo. O fato de o ATT ksh se comportar de maneira diferente é uma indicação de que o zsh não deveria estar fazendo isso. Então, novamente,
$ SHLVL=1 ksh -c 'echo $SHLVL; exec ksh -c "echo \$SHLVL"'
2
3
ksh93 incrementa SHLVL
mesmo com um exec
explícito, e não acho que faça sentido: se o shell está sendo substituído, por que SHLVL
está mudando?