web-dev-qa-db-ja.com

このパイプの最初のコマンドの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

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

私の質問は:

  1. 2つのシェルの動作が異なるのはなぜですか?
  2. bashzshのように動作させる方法はありますか?
3
Kale Kundert

お気づきのように、これを可能にするのがMULTIOSの-​​ zshシェルオプション です。 bashシェルには、同様の組み込み機能はありません。

bashでは、同じ動作が得られます(この特定の例については、以下の ncle Billyのコメント を参照)。

echo foo | { cat; cat bar; }

または

echo foo | cat - bar

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

4
Kusalananda

もう少し時間をかけて調べましたが、zshの動作は MULTIOS option が原因であることがわかりました。これはデフォルトで有効になっています。 bashには同等のオプションがないため、この動作はzshに固有です。

4
Kale Kundert