次の 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 つの読み取り位置のみが含まれます。
別の方法として、ファイル記述子が (OS によって) 作成されると、これらの状態変数を含む構造体/テーブルも作成されます。テーブルには読み取り位置のコピーが 1 つだけ存在し、ファイル記述子で read() 関数が呼び出されるたびに、単一の読み取り位置変数が更新されます。