興味深い質問:-)
CMD は、左から右へのリダイレクトを処理します。最初に 2 (stderr) を &1 (stdout) にリダイレクトし、次に 1 (stdout) を別のものにリダイレクトします。この時点で、stderr は依然として stdout の以前の定義にリダイレクトされます。パイプは stdout (現在は stderr を含む) の古い定義で引き続き機能します。
stdout を気にしない場合は、nul にリダイレクトできます
program.exe 2>&1 1>nul | find " "
stdout をファイルにキャプチャする場合は、ファイルにリダイレクトします
program.exe 2>&1 1>yourFile | find " "
それでもコンソールに stdout を表示したいが、stderr を FIND にパイプしたいだけなら、1 を con にリダイレクトできます:
program.exe 2>&1 1>con: | find " "
stdout と con: の元の定義には微妙な違いがあることに注意してください。たとえばcls >con:
、画面をクリアせず、代わりに面白い文字を画面に出力します。
3 番目 (最初は未使用) のファイル ハンドルを使用すると、stdout と stderr を完全に入れ替えることができます。1 と 3 には stderr の元の定義が含まれ、2 には stdout の元の定義が含まれます。
program.exe 3>&2 2>&1 1>&3 | find " "
実際には、リダイレクトが実行されるたびに定義される追加のファイル ハンドルがあります。元の定義は、最初に使用可能な未使用のファイル ハンドルに保存されます。上記のコマンドを発行する前にリダイレクトが行われていないと仮定します。3>&2
3 は以前に定義されていないため、3 の元の定義は保存されません。ただし2>&1
、stderr の元の定義を 4 に保存し (3 は既に使用されています)、1>&2
stdout の元の定義を 5 に保存します。
したがって、技術的には、stderr と stdout を交換するために 3 の明示的なリダイレクトは必要ありません。
program.exe 2>&1 1>&3 | find " "
2>&1
stderr を 3 に保存し、2 を &1 (stdout) にリダイレクトします。1>&3
stdout を 4 に保存し、1 を &3 (stderr) にリダイレクトします。
ただし、コマンドを発行する前に 3 がまだ定義されていないことが確実な場合にのみ、上記は適切に機能します。前のコード例のように、3 を明示的に定義する方がはるかに安全です。
コマンドの終了後に stderr リダイレクトが終了しないのはなぜですか?を参照してください。どうすれば修正できますか?リダイレクトを使用した本当にワイルドな冒険のために:-)