Em:
selentry='ls -l / | sort ; ts=${PIPESTATUS[0]}'
o mesmo que o mais moderno:
selentry=$(ls -l / | sort ; ts=${PIPESTATUS[0]})
O código dentro do $(...)
é executado em um ambiente subshell (no caso de bash
e shells diferentes de ksh93
, ele é executado em um processo de shell diferente). Portanto, qualquer modificação feita nas variáveis dessa subcamada não afetará o shell pai.
Quando você faz:
var=$(cmd)
No entanto, o status de saída de cmd
é disponibilizado em $?
. Isso não se estende a $PIPESTATUS
, que no caso de:
var=$(foo | bar)
contém apenas um valor (o código de saída do subshell que aqui seria o status de saída de bar
(a menos que a opção pipefail
esteja ativada, caso em que pode ser o status de saída de foo
se não for -zero). É ainda pior em zsh
, onde a matriz $pipestatus
não é afetada pelos comandos de atribuição.
Aqui, porém, se você não se importa com o status de saída de sort
(do subshell), você pode fazer:
selentry=$(ls -l / | sort; exit "${PIPESTATUS[0]}")
ts=$?
Aqui, você também pode fazer:
exec 3< <(ls -l /) # here ls is started as an asynchronous command
ls_pid=$!
selentry=$(sort <&3)
sort_status=$?
wait "$ls_pid"
exec 3<&- # close that fd 3
ls_status=$?
Ou até mesmo:
{
selentry=$(sort)
sort_status=$?
wait "$!"
ls_status=$?
} < <(ls -l /)
Na questão mais geral de que as substituições de atribuições de variáveis sobrevivem a substituições de comandos, em ksh93
, é possível usar a forma ${ cmd;}
de substituição de comando ( ksh93
não suporta $PIPESTATUS
/ $pipestatus
).
var=${
foo; c1=$?
bar; c2=$?
}
Não há equivalente em outros shells semelhantes a Bourne, você precisaria passar os dados por meio de outro meio, como um arquivo temporário:
var=$(
foo; echo "c1=$?" > "$tempfile"
bar; echo "c2=$?" >> "$tempfile"
)
. "$tempfile"
Ou aqui:
selentry=$(
ls -l / | sort
typeset -p PIPESTATUS | sed '1s/PIPESTATUS/my_&/' > "$tempfile"
}
. "$tempfile"
ls_status=${my_PIPESTATUS[0]}