Isso ajuda um pouco se você acha que os descritores de arquivos como variáveis que aceitam um arquivo como um valor (ou o chamam como um fluxo de E / S) e a ordem em que aparecem é a ordem de sua avaliação.
O que acontece no exemplo acima é:
1) O script é iniciado (conforme padrão e, a menos que seja herdado de outra forma) com o seguinte
fd/0 = stdin # that's the keyboard
fd/1 = stdout # that's the screen
fd/2 = stderr # the screen again, but different stream
2) O comando exec
traduz a declaração de uma nova variável e a atribuição de um valor
fd/3 = fd/1 # same as stdout
Agora, dois descritores de arquivo têm o valor stdout, ou seja, ambos podem ser usados para imprimir na tela.
3) antes que ls
seja executado e herde todos os descritores de arquivos abertos, a seguinte configuração acontece
ls.fd/1 = grep.fd/0 # pipe gets precedence, ls.fd/1 writes to grep.stdin
ls.fd/2 = ls.fd/1 # ls.fd/2 writes to grep.stdin
ls.fd/1 = ls.fd/3 # ls.fd/1 writes to stdout
ls.fd/3 = closed # fd/3 will not be inherited by 'ls'
fd / 3 serviu para manter o valor de stdout longo o suficiente para retorná-lo para fd / 1. Então agora tudo o que ls
envia para fd / 1 vai para stdout e não para grep
's stdin.
O pedido é importante, por exemplo se executássemos ls -l >&3 2>&1 3>&-
, ls.fd / 2 escreveria para stdout em vez de stdin grep
.
4) fd / 3 para grep
é fechado e não herdado. Não seria usado de qualquer maneira. grep
só pode filtrar mensagens de erro de ls
O exemplo fornecido no ABSG provavelmente não é o mais útil e o comentário " Fechar fd 3 para 'grep' (mas não 'ls') " é um pouco enganador. Você pode interpretá-lo como: " para o ls, passe o valor de ls.fd / 3 para ls.fd / 1 antes de desfeito, para que ele não seja fechado ".