33

私は WindowsCMD.EXE環境で作業しており、 の出力を の出力とstdout一致するように変更しstderrて、ファイルを介さずにエラー メッセージを他のプログラムにパイプできるようにしたいと考えています。

2>&1表記は承知しておりますが、それはstdoutandstderrを 1 つのストリームにまとめたものです。

私が考えているのは、次のようなものです。

program.exe 2>&1 | find " "

しかし、それは stdout と stderr を次のように組み合わせます。

program.exe | find " " 2>&1

私はできることに気づきました...

program 2>file
type file | find " "
del file

program | find " "しかし、これには一種の記法ほどの柔軟性と力がありません。programこれを行うには、出力を処理する前に がその出力を終了している必要があります。

4

2 に答える 2

48

興味深い質問:-)

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>&23 は以前に定義されていないため、3 の元の定義は保存されません。ただし2>&1、stderr の元の定義を 4 に保存し (3 は既に使用されています)、1>&2stdout の元の定義を 5 に保存します。

したがって、技術的には、stderr と stdout を交換するために 3 の明示的なリダイレクトは必要ありません。

program.exe 2>&1 1>&3 | find " "

2>&1stderr を 3 に保存し、2 を &1 (stdout) にリダイレクトします。1>&3stdout を 4 に保存し、1 を &3 (stderr) にリダイレクトします。

ただし、コマンドを発行する前に 3 がまだ定義されていないことが確実な場合にのみ、上記は適切に機能します。前のコード例のように、3 を明示的に定義する方がはるかに安全です。

コマンドの終了後に stderr リダイレクトが終了しないのはなぜですか?を参照してください。どうすれば修正できますか?リダイレクトを使用した本当にワイルドな冒険のために:-)

于 2012-09-05T03:34:09.257 に答える
3

http://support.microsoft.com/kb/110930を見ると、あなたが望むようです2>&1 1>NUL。したがって、次のようなものがうまくいくはずです。

test.exe 2>&1 1>NUL | find "someErrorString"
于 2012-09-05T03:34:37.420 に答える