Você pode ler sobre esta sintaxe na página man bash sob Substituição de processos :
>(list)
. The process list is run with its output connected to some file in /dev/fd. The name of this file is passed as an argument to the current command as the result of the expansion.
Veja a saída deste comando que não faz nenhum redirecionamento:
echo >(echo hi >/tmp/a) >(echo lo >/tmp/b)
é (no meu sistema):
/dev/fd/63 /dev/fd/62
Portanto, você deve ler 1> >(...)
as 1>
e >(...)
. A segunda parte é substituída por /dev/fd/63
, e então temos 1> /dev/fd/63
, então redirecionamos o stdout para o descritor de arquivo 63.
bash executa o comando dentro de >(...)
em um processo separado e conecta o stdin desse processo ao descritor de arquivo 63. Confira este exemplo:
set -x
echo hello > >(cat -n)
A stdout do eco é canalizada para a entrada de cat -n
e você obtém:
+ echo hello
++ cat -n
1 hello
Talvez o que esteja faltando é que quando você tem um descritor de arquivo (fd) para um arquivo, e então garfo o processo (que o bash está fazendo com >(...)
), você pode herdar o mesmo fd no novo processo. Portanto, os dois processos compartilham o mesmo fd. Além disso, existe apenas um arquivo offset para um fd, então se o processo 1 escreve 3 caracteres para o fd, então o deslocamento se move de 0 para 3. Se o processo 2 então escreve 5 caracteres para o fd, os dados são colocados no deslocamento 3 e o deslocamento se torna 8. Se o processo 1 gravar outro caractere, ele será colocado no deslocamento 8 e assim por diante. É assim que os dois comandos tee
em sua pergunta conseguem gravar no mesmo arquivo all
sem sobrescrever um ao outro.
Usar >&3
não cria um novo fd; simplesmente fecha o stdout atual fd 1, depois renumera fd 3 para fd 1. Portanto, ainda existe apenas um fd para os dois processos, mesmo se o número agora visto por cada processo for diferente (veja man dup2
para a chamada de sistema subjacente). ).