У меня есть файл, содержащий четыре строки:
$ cat file
First line
Second line
Third line
Fourth line
$
Когда я читаю этот файл четыре раза, я всегда читаю первую строку, что является ожидаемым результатом:
$ for i in {1..4}; do read line <file; echo "$line" ; done
First line
First line
First line
First line
$
Однако когда я связываю файловый дескриптор 3 с file
и затем читаю его таким же образом, то каждое чтение «съедает» входной поток:
$ exec 3<file
$ for i in {1..4}; do read -u 3 line; echo "$line" ; done
First line
Second line
Third line
Fourth line
$
Почему дескрипторы файлов ведут себя таким образом?
решение1
Когда вы говорите: read var <file
дескриптор файла закрывается после завершения команды. Следовательно, в следующий раз в цикле дескриптор файла сбрасывается в начало.
В случае exec 3<file
, когда вы говорите, read -r -u 3 var
что дескриптор файла остается открытым даже после завершения команды чтения И позиция чтения обновляется, поэтому в следующий раз чтение захватит следующую строку.
Примечание: Даже если вы это сделали, то exec 0<file
и тогда read -r var
он все равно будет вести себя аналогично.
решение2
Быстрый ответ заключается в том, что они так и задуманы — файловый дескриптор содержит состояние, которое включает позицию чтения и записи. Каждое чтение, выполненное на одном файловом дескрипторе, перемещает позицию чтения, независимо от того, кто читает из него — файловый дескриптор содержит только одну позицию чтения.
Другим способом, когда создается дескриптор файла (ОС), он также создает структуру/таблицу, содержащую эти переменные состояния. В таблице есть только одна копия позиции чтения, и каждый раз, когда функция read() вызывается для дескриптора файла, обновляется единственная переменная позиции чтения.