ファイル記述子の読み取りに失敗しました。

ファイル記述子の読み取りに失敗しました。

この質問は、ファイル記述子を読み書きすることに関するものです。次の例をご覧ください。

#!/bin/sh

file='somefile'

# open fd 3 rw
exec 3<> "$file"

# write something to fd 3
printf "%s\n%s\n" "foo" "bar" >&3

# reading from fd 3 works
cat "/proc/$$/fd/3"

# only works if the printf line is removed
cat <&3

exit 0

スクリプトは以下を出力します。

foo
bar

予想出力:

foo
bar
foo
bar

ファイル記述子を開いて書き込むことに成功しました。読書も同じだproc/$$/fd/3。しかし、これは持ち運びが容易ではないcat <&3何も出力しません。ただし、ファイルディスクリプタが作成されていない場合(たとえば、その行のコメントアウトを削除するなど)はprintf機能します。

なぜ動作しないのか、cat <&3そしてポータブルファイル記述子(POSIXシェル)から内容全体をどのように読み取ることができますか?

ベストアンサー1

cat <&3ファイルの終わりに達するまで、ファイルから読み取る操作を正確に実行します。呼び出すと、ファイル記述子のファイルの場所は最後に離れた場所、つまりファイルの終わりです。 (読み取りと書き込みのための別の場所ではなく、1つのファイルの場所があります。)

cat /proc/$$/fd/3同じことはしませんcat <&3。別の記述子で同じファイルを開きます。各ファイル記述子には固有の場所があり、ファイルを読み取るために開くと場所が0に設定されるため、このコマンドはファイル全体を印刷し、スクリプトには影響しません。

作成した内容を再度読み取るには、ファイルを再度開くか、ファイル記述子を巻き戻す必要があります(たとえば、場所を0に設定)。 POSIXシェルとほとんどのsh実装にはこれを行う組み込み方法はありません(ksh93に1つあります)。追求すべきユーティリティは1つだけです。ddしかし、今後のみナビゲートできます。 (これから飛び越えることができる他のユーティリティがありますが、これは役に立ちません。)

唯一のポータブルソリューションは、ファイル名を覚えており、必要に応じて何度も開くことだと思います。ファイルが通常のファイルではない場合は、以前のバージョンを確認できない場合がありますのでご注意ください。

おすすめ記事