Eu tenho um arquivo que contém quatro linhas:
$ cat file
First line
Second line
Third line
Fourth line
$
Quando leio este arquivo quatro vezes, sempre leio a primeira linha, que é um resultado esperado:
$ for i in {1..4}; do read line <file; echo "$line" ; done
First line
First line
First line
First line
$
No entanto, quando vinculo o descritor de arquivo 3 file
e o leio da mesma maneira, cada leitura "come" o fluxo de entrada:
$ exec 3<file
$ for i in {1..4}; do read -u 3 line; echo "$line" ; done
First line
Second line
Third line
Fourth line
$
Por que os descritores de arquivos se comportam assim?
Responder1
Quando você diz: read var <file
o descritor de arquivo é fechado assim que o comando termina. Portanto, na próxima vez no loop, o descritor de arquivo será redefinido para o início.
No caso de exec 3<file
, quando você diz que read -r -u 3 var
o descritor de arquivo permanece aberto mesmo quando o comando de leitura termina E a posição de leitura é atualizada para que da próxima vez, a leitura pegue a próxima linha.
Nota: Mesmo que você tenha feito isso, exec 0<file
ele read -r var
ainda se comportará de maneira semelhante.
Responder2
A resposta rápida é que eles foram projetados para funcionar - um descritor de arquivo contém um estado, que inclui uma posição de leitura e gravação. Cada leitura realizada em um descritor de arquivo move a posição de leitura, não importa quem esteja lendo - o descritor de arquivo contém apenas uma posição de leitura.
De outra forma, quando um descritor de arquivo é criado (pelo sistema operacional), ele também cria uma estrutura/tabela que contém essas variáveis de estado. Há apenas uma cópia da posição de leitura na tabela e cada vez que a função read() é chamada no descritor de arquivo, a única variável de posição de leitura é atualizada.