Você perceberá que em bash / ksh
echo foo | echo "$(cat)"
exibe foo , mas
<<< foo echo "$(cat)"
Não.
No primeiro caso, o $(cat) é expandido no processo filho que executará echo depois que seu stdin for redirecionado do canal.
No segundo caso, o $(cat) é expandido antes do redirecionamento.
pipes e redirecionamentos são coisas diferentes. pipes envolvem algum redirecionamento , mas também iniciam comandos em paralelo. Isso acontece cedo, antes dos redirecionamentos dentro de cada componente do pipe.
Em zsh
$ sleep 1 | ps -jfH $(ps -fH >&2)
UID PID PPID C STIME TTY TIME CMD
chazelas 2495 2494 0 20:59 pts/1 00:00:00 /bin/zsh
chazelas 31201 2495 0 21:20 pts/1 00:00:00 sleep 1
chazelas 31202 2495 0 21:20 pts/1 00:00:00 ps -fH
UID PID PPID PGID SID C STIME TTY TIME CMD
chazelas 2495 2494 2495 2495 0 20:59 pts/1 00:00:00 /bin/zsh
chazelas 31201 2495 31201 2495 0 21:20 pts/1 00:00:00 sleep 1
chazelas 31203 2495 31201 2495 0 21:20 pts/1 00:00:00 ps -jfH
Você notará que, desta vez, a substituição do comando é expandida pelo shell pai.
Uma coisa a ter em mente é que, em zsh , os pipes são tratados um pouco mais como redirecionamentos em particular quando se trata da opção mult_ios (ativada por padrão).
Quando você faz:
echo foo > file | tr o e
foo vai para os dois file e tr .
Em:
uname | cat < /etc/issue
cat é alimentado com a saída de uname e o conteúdo de /etc/issue . Portanto, em zsh , o redirecionamento de < / > e do pipe deve acontecer no mesmo estágio. De preferência após as expansões.
Em qualquer caso, você sempre pode fazer:
echo foo | { echo "$(cat)"; }
em zsh e bash / ksh , como sempre é possível fazer:
{ echo "$(cat)"; } <<< foo
em bash e zsh .
Quanto à causa do:
tail: error reading 'standard input': Input/output error
erro. Em shells interativos, uma vez que a substituição de comandos é feita no pai, isso não é feito no grupo de processos em primeiro plano do terminal.
tail será executado no grupo de processos do shell pai. Se esse shell for o líder da sessão, ele será um grupo de processos órfãos , portanto quando tail tentar ler o dispositivo tty, ele falhará com a EIO.
Se zsh não foi o líder da sessão. Por exemplo, se você iniciou zsh de outro shell, o grupo de processos receberia um SIGTTIN. O processo principal do shell iria ignorá-lo, mas tail acabaria sendo suspenso.