Tengo un archivo que contiene cuatro líneas:
$ cat file
First line
Second line
Third line
Fourth line
$
Cuando leo este archivo cuatro veces, siempre leo la primera línea, que es un resultado esperado:
$ for i in {1..4}; do read line <file; echo "$line" ; done
First line
First line
First line
First line
$
Sin embargo, cuando vinculo el descriptor de archivo 3 file
y luego lo leo de la misma manera, cada lectura "come" el flujo 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 qué los descriptores de archivos se comportan así?
Respuesta1
Cuando dices: read var <file
el descriptor de archivo se cierra una vez que finaliza el comando. Por lo tanto, la próxima vez en el bucle, el descriptor de archivo se restablece al principio.
En el caso de exec 3<file
, cuando dice que read -r -u 3 var
el descriptor de archivo permanece abierto incluso cuando finaliza el comando de lectura Y la posición de lectura se actualiza, de modo que la próxima vez, la lectura tomará la siguiente línea.
Nota: Incluso si lo hubiera hecho, exec 0<file
seguirá read -r var
comportándose de manera similar.
Respuesta2
La respuesta rápida es que así es como están diseñados para funcionar: un descriptor de archivo contiene un estado, que incluye una posición de lectura y escritura. Cada lectura realizada en un descriptor de archivo mueve la posición de lectura, sin importar quién esté leyendo: el descriptor de archivo solo contiene una posición de lectura.
De otra manera, cuando se crea un descriptor de archivo (por el sistema operativo), también crea una estructura/tabla que contiene estas variables de estado. Solo hay una copia de la posición de lectura en la tabla, y cada vez que se llama a la función read() en el descriptor de archivo, se actualiza la variable de posición de lectura única.