パイプラインは | で区切られたコマンドのリストです。指定したリダイレクトは構成コマンド (単純または複合) に適用されますが、パイプライン全体には適用されません。各パイプは、コマンドに関連付けられたリダイレクトが評価される前に、暗黙的に各サブシェルにリダイレクトを適用することにより、1 つのコマンドの stdout を次の stdin にチェーンします。
cmd 2>&1 | less
最初のサブシェルの最初の stdout は、less読み取り元のパイプにリダイレクトされます。次に、2>&1最初のコマンドにリダイレクトが適用されます。stdout は既にパイプを指しているため、stderr を stdout にリダイレクトすると機能します。
cmd | less 2>&1
ここで、リダイレクトは に適用されlessます。Less の stdout と stderr はどちらも端末を指していると思われるため2>&1、この場合は効果がありません。
リダイレクトをパイプライン全体に適用したり、パイプラインの一部として複数のコマンドをグループ化したり、パイプラインをネストしたりする場合は、コマンド グループ (またはその他の複合コマンド) を使用します。
{ { cmd1 >&3; cmd2; } 2>&1 | cmd3; } 3>&2
典型的な例かもしれません。最終結果は次のとおりです。 cmd1andcmd2の stderr -> cmd3; cmd2の標準出力 -> cmd3; およびの stderr、およびcmd1のstdout -> 端末。cmd3cmd3
Bash 固有の|&パイプを使用すると、パイプラインの stdout リダイレクトはそれぞれ最初に発生しますが、stderr リダイレクトは実際には最後に発生するため、事態はさらに奇妙になります。たとえば、次のようになります。
f() { echo out; echo err >&2; }; f >/dev/null |& cat
ここで、直感に反して、すべての出力が非表示になります。の最初の stdout がfパイプに移動し、次の stdout がfにリダイレクトされ/dev/null、最後に stderr が stdout (/dev/null静止) にリダイレクトされます。
|&Bashでは絶対に使用しないことをお勧めします。ここではデモ用に使用しています。