4行のファイルがあります。
$ cat file
First line
Second line
Third line
Fourth line
$
このファイルを4回読み取ると、常に最初の行が読み取られました。これは予想される結果です。
$ 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
簡単な答えはこれがうまくいく方法です。ファイル記述子には、読み書き位置を含む状態が含まれています。ファイル記述子に対して実行された各読み取りは、読み取り者に関係なく読み取り位置を移動します。ファイル記述子には1つの読み取り位置のみが含まれます。
つまり、ファイル記述子がオペレーティングシステムによって生成されると、これらの状態変数を含む構造/テーブルも作成されます。テーブルには読み取り位置のコピーが 1 つだけあり、ファイル記述子で read() 関数が呼び出されるたびに、単一の読み取り位置変数が更新されます。