web-dev-qa-db-ja.com

bashの<()(およびzshの=())とは正確には何ですか?

私はbashにはかなり慣れていますが、最近、知らない人になりました。

Bashの<(<command>)とは正確には何ですか? zshの=(<command>)と比較してどうですか?

これはデフォルトのファイル記述子と関係があることを理解しています。私のコンピューター

echo <()

戻り値 /proc/self/fd/11、これはスクリプトSTDOUTのコピーであることがわかりましたが、それでも私にはかなり混乱しているようです。

38

これはプロセス置換と呼ばれます。

<(list)構文は bashzsh の両方でサポートされています。パイプ(_|_)を使用できない場合に、コマンド(list)の出力を別のコマンドに渡す方法を提供します。たとえば、コマンドがSTDINからの入力をサポートしていない場合、または複数のコマンドの出力が必要な場合:

_diff <(ls dirA) <(ls dirB)
_

<(list)は、listの出力を_/dev/fd_のファイルに接続します(システムでサポートされている場合)。そうでない場合は、名前付きパイプ(FIFO)が使用されます(これは、システム;どちらのマニュアルも、両方のメカニズムがサポートされていない場合にどうなるかについては述べていません。おそらくエラーで中止されます)。次に、ファイルの名前がコマンドラインの引数として渡されます。


zshは、=(list)の可能な代替として<(list)を追加でサポートします。 =(list)では、_/dev/fd_またはFIFOのファイルの代わりに一時ファイルが使用されます。プログラムが出力でlseekする必要がある場合、<(list)の代わりとして使用できます。

ZSHマニュアル によると、<(list)の動作には他にも問題がある可能性があります。

_=_形式は、_/dev/fd_と<(...)の名前付きパイプ実装の両方に欠点があるため、便利です。前者の場合、特にプログラムがsetuidを実行しているときなどのセキュリティ上の理由で必要な場合、一部のプログラムはコマンドラインでファイルを調べる前に問題のファイル記述子を自動的に閉じることがあります。 2番目のケースでは、プログラムが実際にファイルを開かない場合、パイプからの読み取りまたはパイプへの書き込みを試みるサブシェルは(通常の実装では、異なるオペレーティングシステムでは異なる動作をする場合があります)ブロックし、明示的に強制終了する必要があります。 。どちらの場合も、シェルは実際にはパイプを使用して情報を提供するため、ファイルでlseek(manページlseek(2)を参照)を期待するプログラムは機能しません。

55
Adaephon

これはzshではなくbashの回答です。

Bashでパイプを使用できない場合があります。

_some_command | some_other_command
_

パイプはパイプラインの各コンポーネントにサブシェルを導入するため、サブシェルが終了すると、依存していた副作用はなくなります。たとえば、この不自然な例:

_cat file | while read line; do ((count++)); done
echo $count
_

_$count_変数が現在のシェルに存在しないため、空白行が表示されます。

Bash プロセス置換 を使用すると、ファイルの場合と同じように「some_command」出力から読み取ることができるため、この難問を回避できます。

_while read line; do ((count++)); done < <(cat file)
# ....................................1.2
echo $count   # the variable *does* exist in the current Shell
_

(1)は通常の入力リダイレクトです。 (2)は、<()プロセス置換構文の始まりです。

11
glenn jackman