Namedpipeを一時ファイルとして使用するには?

Namedpipeを一時ファイルとして使用するには?

私が使用しているvimプラグインは、このスクリプトを使用してstdinでの読み取りをサポートしていないlinterにいくつかの入力を渡します。

set -eu

# All of the following arguments are read as command to run.
file_extension="$1"
shift

temp_dir=$(mktemp -d 2>/dev/null || mktemp -d -t 'ale_linter')
temp_file="$temp_dir/file$file_extension"
trap 'rm -r "$temp_dir"' EXIT

while read -r; do
  echo "$REPLY" >> "$temp_file"
done

"$@" "$temp_file"

最初は、なぜ彼らが次のようなものを使用しないのか、少し混乱しました。

some input | some_program /dev/stdin

しかし、ghcリンターで試した後、私は/ dev / stdinが実際のファイルではないと文句を言うことを発見しました(そうではありませんでした)。

それで、一時ファイルの代わりに名前付きパイプを使用できるかどうか疑問に思います。私が一時ファイルに書き込むのが気に入らない理由はSSDの状態のためですが、もっと良い方法があればそうすればどうでしょうか?

答え1

いいえ、これらのファイルを拒否するプログラムは通常、ファイルが無効であるため、そのファイルを拒否します。閲覧可能(任意のオフセットでコンテンツにアクセスする必要があるか、巻き戻しなどを行った後に何度もアクセスする必要があります。)またはファイルを何度も開きたいです。また、ファイル(ファイルの一部)を書き換えたり、切り取りたい場合もあります。

名前が指定されているかpipe|およびのように/dev/stdin)名前が指定されている場合、そのような場合には違いはありません。

実際、Linuxでは、stdinがパイプ(名前または存在しない)の場合、これは名前付きパイプと同じように動作し、プログラムはそれを実際の名前付きパイプと区別することはでき/dev/stdinません。/dev/stdin

他のシステムではまったく同じではありませんが、実際に/dev/stdinパイプを開くか名前を付けると、パイプのファイル記述子が提供されるため、どちらも検索できません。

したがって、一時ファイルを生成する必要があります。これをより簡単にするシェルがあります。の場合はzsh次のようになります。

#! /bin/zsh -
"$@" =(cat)

Linuxでは、ここで説明されているように、削除された一時ファイルをシェルとして使用することができます(たとえば、およびのbash一部zshの実装ksh)。

#! /bin/bash -
"$@" /dev/fd/3 3<< EOF
$(cat)
EOF

ただし、ファイルにNUL文字が含まれているか空白行で終わると、ファイルの内容が破損する可能性があります。

バージョン5以降、bashは文書一時ファイルを読み取り専用にするため、アプリケーションがファイルを変更する必要がある場合は、次のように書き込み権限を復元します。

#! /bin/bash -
{
  chmod u+w /dev/fd/3 && # only needed in bash 5+
    "$@" /dev/fd/3
} 3<< EOF
$(cat)
EOF

while read要求された後のループに関するメモです。

まず、変数名がないread -rのは間違った構文です。shこの構文は、ISO 9899で指定された構文shと同様に、POSIX(ISO 9945、IEEE Std 1003.1)によって指定されます。C

存在する仕様read、変数名引数が必要であることがわかります。省略したときの動作は次のとおりです。指定されていないそして実際にはshインタプリタの実装によって異なります。

bashGNU Cコンパイラと同様に、GNUshインタプリタです。どちらもこの規格で指定された内容を拡張します。gccbashgcc

それに関する限りread、そう扱ってくださいbash。 POSIX仕様は、文字または入力の終わりに達するまでstdinを読み取り、読み取った文字を変数に保存して返します。read -rIFS= read -r REPLYIFS= read -r REPLY\n$REPLY成功改行文字(全行)を読み込んだ場合、終了状態または失敗するそうでない場合(たとえば、改行の前のEOF)、読み取られたデータにNUL文字または有効な文字を形成しないバイトシーケンスが含まれている場合、動作は定義されません。

この場合、bash読み取ったバイトが有効な文字ではない場合でも、それを保存してNUL文字を削除します。

read -rまたは、ベースのPOSIX様シェルのエラー報告read -r REPLYに似ています。kshzshyashash

echoその引数にバックスラッシュ文字が含まれておらず、最初の文字が含まれていない限り、動作は指定されません-n

したがって、要約すると、sh扱っている特定の実装(およびバージョン)がわからない限り、何も言えません。

while read -r; do
  echo "$REPLY" >> "$temp_file"
done

します。特定の場合には、bashデータに NUL 文字が含まれず、改行文字で終わり、拡張正規表現に一致する^-[neE]+$行がない場合にのみ (および/または環境や OS/Xbashなどのコンパイルされた方法によってshバックスラッシュが含まれない) 文字) 。

これも非常に非効率的で、シェルでテキストを処理する方法ではありません。

希望する場所は次のとおりです。

cat > "$temp_file"

cat標準コマンド、引数が指定されていない場合は、単に標準入力を標準出力にダンプします。現状のまま

関連情報