cmd x>&y diz: "redireciona fd x para qualquer recurso que fd y é redirecionado para"
Então, em:
cat 1>&3 3>&1
Você está dizendo que o fd 1 (stdout) de cat deve ir para o mesmo recurso que o aberto no fd 3, que é ./tmp aberto no modo de leitura + gravação; e depois fd 3 para o mesmo recurso que o aberto no fd 1, que você acabou de fazer para ser ./tmp .
Portanto, cat será iniciado com seus fds 1 e 3 redirecionados para ./tmp . cat não faz nada com o seu fd 3, você pode redirecionar o fd 3 do cat para qualquer coisa que você goste, ele não terá efeito.
No entanto, ele grava o conteúdo de file em seu fd 1, portanto, você encontrará o conteúdo de file escrito no início de ./tmp .
cat file grava o conteúdo de file apenas uma vez e apenas para um fd. Se você quiser algo que grave o conteúdo de file duas vezes em dois fds diferentes, convém tee :
Em
< file tee ./tmp
tee escreveria o que lê em seu fd 0 (aqui redirecionado para file aberto no modo somente leitura) para ./tmp (aberto no modo somente gravação com truncamento) e seu fd 1 (stdout) .
Embora seja possível informar tee para abrir ./tmp no modo acrescentar com -a , não é possível dizer para abrir ./tmp no modo de leitura + gravação sem truncamento como 3<> faz.
Para isso, você precisaria:
< file tee /dev/fd/3 3<> ./tmp
que funcionaria, exceto no Linux, ou recorrer ao uso de zsh e seu recurso de armazenamento interno:
cat < file 3<> ./tmp >&1 >&3 3>&-
Com o fd 1 sendo redirecionado duas vezes, zsh , quando a opção mulltios está habilitada (ativada por padrão), faria um tee interno para encaminhar a saída para ambos os destinos (executando um processo interno que lê cat de saída e grava em ambos os destinos).
O uso temporário de fd 3 é para contornar o problema que em
cat < file >&1 1<> ./tmp
zsh reclama com zsh: file mode mismatch on fd 1 , pois supõe que você queira ler em ./tmp .