$(…)
é um subshell por definição: é uma cópia do estado de tempo de execução do shell¹, e alterações no estado feito no subshell não causam impacto no pai. Um subshell é tipicamente implementado por forking um novo processo (mas alguns shells podem otimizar isso em alguns casos). / p>
Não é um subshell que você pode recuperar valores de variáveis. Se as alterações nas variáveis tivessem um impacto no pai, não seria uma sub-novidade. É um subshell cujo output o pai pode recuperar. O subshell criado por $(…)
tem sua saída padrão definida como um pipe, e o pai lê desse pipe e coleta a saída.
Existem várias outras construções que criam um subshell. Eu acho que esta é a lista completa de bash:
- Subshell para o agrupamento :
( … )
não faz nada mas crie uma subshell e espere que ela termine). Contraste com{ … }
, que agrupa comandos puramente para propósitos sintáticos e não cria um subnível. -
Background :
… &
cria uma subshell e não espera que ela termine. -
Pipeline :
… | …
cria duas subpavinas, uma para o lado esquerdo e um para o lado direito, e aguarda que ambos terminem. O shell cria um pipe e conecta a saída padrão do lado esquerdo à extremidade de gravação do pipe e a entrada padrão do lado direito ao terminal de leitura. Em alguns shells (ksh88, ksh93, zsh, bash com olastpipe
option definido e efetivo), o lado direito é executado no shell original, portanto, a construção do pipeline cria apenas um subshell. -
Substituição de comandos :
$(…)
(também escrito'…'
) cria uma subshell com sua saída padrão definida para um pipe, coleta a saída no pai e se expande para essa saída, menos suas novas linhas finais. (E a saída pode estar sujeita a divisão e globbing, mas isso é outra história.) -
Processo de substituição :
<(…)
cria um subshell com seu padrão saída definida para um pipe e se expande para o nome do pipe. O pai (ou algum outro processo) pode abrir o pipe para se comunicar com o subshell.>(…)
faz o mesmo, mas com o pipe na entrada padrão. -
Coprocess :
coproc …
cria uma subshell e não espera que ela termine . A entrada e a saída padrão do subshell são definidas para um pipe com o pai sendo conectado à outra extremidade de cada pipe.