Por que a leitura funciona se o stdin é redirecionado para o fd4?

Por que a leitura funciona se o stdin é redirecionado para o fd4?

O que significa o script a seguir?

exec 4<&0 0</etc/XX/cfg
read line1
exec 0<&4

Ele redireciona fd0 para fd4 e "/etc/XX/cfg" para fd0.

Então, por que readainda funciona, não deveria estar vazio?

Responder1

Ele redireciona stdin (FD0) para FD4, redireciona de /etc/XX/cfgpara FD0, lê uma linha de FD0 e então move FD4 de volta para FD0. Resumindo, ele salva, substitui e restaura stdin, enquanto lê uma linha de um arquivo intermediário.

read line1 < /etc/XX/cfgseria muito mais fácil, mas é impossível dizer se é uma substituição válida com base apenas no código mostrado.

Responder2

Para reformular isso em syscalls (usando C):

exec 4<&0 0</etc/XX/cfg

/* Duplicate fd0 as fd4.  */
dup2 (0, 4);

/* Open file on fd0.
   "open" always uses lowest available descriptor, so we don't need to check it. */
close (0);
open ("/etc/XX/cfg", O_RDONLY);

exec 0<&4

/* Close fd0 and duplicate fd4 as fd0.  */
dup2 (4, 0);

Responder3

A maneira como li isso - com base na seção da página de manual do bash em REDIRECTION - é que stdin(fd0) é redirecionado para fd4, então a entrada é obtida de /etc/XX/cfginto stdin- que terminará em fd4.

read line1deve então pegar de fd4 que é então colocado de volta em fd0.

Uma demonstração pode mostrar um pouco melhor o que quero dizer e responder "por que" você pode fazer isso. Adicionando outra linha e colocando-a em um wrapper:

$ vim ./test.sh
#!/bin/bash
exec 4<&0 0</etc/XX/cfg
read line1    # reads from fd4
exec 0<&4
read line2    # reads from fd0

echo $line1 
echo $line2

Você pode canalizar ou redirecionar stdinvia test.sh, mas também ler a configuração por redirecionamento, portanto, no código acima, extraí valores de "config" (suposição de minha parte com base no nome do arquivo - ruim :)), mas eu também pode processar via stdin.

por exemplo:

$ ./test.sh < somefile
$ cat somefile | ./test.sh

Espero que isso explique tudo.

informação relacionada