Давайте немного упростим это:
$ 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
Происходит то, что если последняя команда является внешней командой, zsh выполняет ее без разветвления - оптимизация хвостового вызова . Вы можете увидеть это, повторив $$
в дополнение к SHLVL
: в первом случае вложенный вызов zsh имеет тот же PID; во втором случае вложенный вызов выполняется как дочерний процесс, потому что родительский процесс остается, чтобы впоследствии выполнить true
.
Вы видите другое поведение sh
, потому что оно ведет себя по-другому. Возможно, ваш sh
- это bash, который не выполняет никакой оптимизации хвостового вызова. Или, может быть, это ksh93, который выполняет оптимизацию хвостового вызова, но увеличивает SHLVL
даже в этом случае.
Должен ли zsh увеличивать SHLVL
в хвостовом вызове? Для этого нет официального стандарта, но это имело бы смысл, поскольку предполагается, что хвостовые вызовы являются оптимизацией, и, кроме процедур, я ожидаю, что поведение будет таким же. Тот факт, что ATT ksh ведет себя иначе, указывает на то, что zsh не должен этого делать. Опять же,
$ SHLVL=1 ksh -c 'echo $SHLVL; exec ksh -c "echo \$SHLVL"'
2
3
ksh93 увеличивает SHLVL
даже с явным exec
, и я не думаю, что это имеет смысл: если оболочка заменяется, почему SHLVL
изменение?