このパイプの最初のコマンドからの stdout が処理されないのはなぜですか?

このパイプの最初のコマンドからの stdout が処理されないのはなぜですか?

私は、(i) stdin からの読み取りと (ii) パイプからの読み取りを同時に実行できるコマンドを作成しようとしています。この基本概念は では機能しますzshが、 では機能しませんbash。次のセッションは、2 つのシェルの動作の違いを示しています。

$ echo bar > bar
$ zsh -f
zsh-5.8$ echo foo | cat < bar
foo
bar
zsh-5.8$ exit
$ bash --noprofile --norc
bash-5.0$ echo foo | cat < bar
bar

上記のコマンドはcatstdin の 2 つのソース (パイプとリダイレクト) を提供するため、これをどのように処理するかがあいまいである可能性があります。 は、 zsh2 つの入力ストリームを連結しているように見えますが、パイプされた入力は常に最初に来ます。 は、 bashパイプされた入力を単にドロップしているように見えます。

私の質問は次のとおりです:

  1. なぜ 2 つのシェルの動作が異なるのでしょうか?
  2. bashのように動作するように強制する方法はありますかzsh?

答え1

ご存知のとおり、MULTIOSシェルオプションzshこれを可能にします。シェルには同様の組み込み機能はありませんbash

ではbash、同じ動作になります(この特定の例では、ビリーおじさんのコメントは以下) から

echo foo | { cat; cat bar; }

または

echo foo | cat - bar

これら右側の両辺は、 を読み取る前にまず標準入力を読み取りますbar

答え2

私はもう少し時間をかけてこれを調べ、の挙動zshMULTIOSオプションはデフォルトで有効になっています。 には bash同等のオプションがないようですので、この動作は に固有のものですzsh

関連情報