我有一个包含四行的文件:
$ 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
$
但是,当我链接文件描述符 3file
然后以相同的方式读取它时,每个读取都会“吃掉”输入流:
$ 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() 函数时,都会更新单个读取位置变量。