sed -iが/proc/PID/fd/FDで動作しない理由

sed -iが/proc/PID/fd/FDで動作しない理由

私はこのファイルとfdを持っています:exec 88<>abc

なぜ

$ sed -i "s/cd/II/g" /proc/$$/fd/88
sed: couldn't open temporary file /proc/26194/fd/sedS1D1FT: No such file or directory

しかし、これはうまくいきます:

$ cat /proc/self/fd/88 | sed  "s/cd/II/g" 
abIIefg

その後、これは機能しません。

$ (cat /proc/self/fd/88 | sed  "s/cd/II/g")  > /proc/self/fd/88

/proc/self/fd/88これにより空になります。

答え1

sed -iファイルは実際には「その場で」編集されません。出力を一時ファイルにリダイレクトし、一時ファイルの名前を変更するか、元のファイルに移動するように機能します。

これにより、途中で問題が発生しても元のファイルが失われることはありません。

さらに悪いことは、sed(たとえばvim)元のファイルと同じディレクトリに一時ファイルを作成しようとすることです。

ファイル/procシステムは人工、その中にファイルを作成または移動できないため、対応するエラーが発生します。ただし、sed一時ファイルがから作成されても、最後の/tmp操作(一時ファイルを元のファイルに名前変更)はまだ失敗します。

sed -iロータリー方式で試すことができます。

$ ised(){ for a; do :; done; t=`mktemp` && sed "$@" > "$t" && cat "$t" > "$a" && rm "$t"; }
$ ised s/cd/II/g /proc/$$/fd/88

ファイル名は常にised

これは一貫性の保証を破りますsed -i。とは異なり、cat in > out作業はrename("in", "out")原子的ではありません。途中で停止すると、outファイルは切り捨てられます。

答え2

実際のファイルがまだ存在すると仮定すると、これはより良い可能性があります(ただし、実際のファイルを変更するので注意して使用してください)。

sed -i s/cd/II/g "$(realpath "/proc/$$/fd/88")"

〜のようにモスビーノート、の結果がrealpath /proc/$$/fd/88削除された場合、この操作は何の効果もありません。例:

exec 7>/tmp/junk; echo yes >&7; rm /tmp/junk; 
cat /proc/$$/fd/7; cat "$(realpath "/proc/$$/fd/7")"

出力(にもかかわらず/tmp/ジャンク存在しない)、最初の行標準出力、ライン2~標準エラーエラー率:

yes
cat: '/tmp/junk (deleted)': No such file or directory

関連情報