A primeira parte desta resposta é que jobs
e dirs
são built-ins, então tipicamente o bash apenas os executa diretamente ao invés de invocar um subshell.
Isso é verdade para os casos em que há canais ou substituição de comando ( $(jobs)
) ou substituição de processo ( <(jobs)
).
Este não é realmente o caso para executar o comando em segundo plano ( jobs &
) ou solicitar explicitamente uma subshell (com ( jobs )
.)
Isso explica a última parte da sua pergunta. Quando você executa jobs
em um subshell, ele realmente mostra os jobs para o subshell em si.
Aqui está uma boa demonstração desse conceito:
$ sleep 1001 &
[1] 15927
$ sleep 1002 &
[2] 15940
$ jobs
[1]- Running sleep 1001 &
[2]+ Running sleep 1002 &
$ ( sleep 1003 & jobs )
[1]+ Running sleep 1003 &
$ jobs
[1]- Running sleep 1001 &
[2]+ Running sleep 1002 &
Você verá que o caso em que jobs
está sendo executado em um subshell, apenas os jobs desse subshell (neste caso sleep 1003
) serão exibidos.
Agora, para encerrar, precisamos abordar a parte intermediária da pergunta, e é por isso que dirs &
(que de fato é executado em um subshell, assim como ( dirs )
) ainda mostrará os diretórios salvos no pushd pilha.
Acontece que isso ocorre porque o shell exporta a lista de diretórios na variável de matriz especial DIRSTACK
, que é então herdada por subshells. (Você pode ler mais sobre DIRSTACK
aqui .)
Uma maneira de demonstrar como isso funciona é usar pushd
no subshell e ver como isso não afeta a pilha de diretórios do shell original:
$ dirs
~
$ pushd ~/tmp
~/tmp ~
$ ( dirs; pushd / >/dev/null; dirs )
~/tmp ~
/ ~/tmp ~
$ dirs
~/tmp ~
Acredito que deve abordar todos os itens que você perguntou.
UPDATE : o bash tem uma disposição especial para tornar jobs | less
work, tendo o comando jobs
executado no shell atual (que não é o caso de outros built-ins).
O código tem uma verificação que é armazenada em uma variável jobs_hack
, que é posteriormente verificada para torná-lo executado sem criar um sub-shell e permitir a saída de jobs
para outro comando.
Veja aqui para a parte relevante do código-fonte que implementa isso. (A partir do ano 4.4)