Existe uma maneira de redirect apenas stderr para stdout (não combinar os dois) para que possa ser canalizado para outros programas?

Eu estou trabalhando em um ambiente Windows CMD.EXE e gostaria de alterar a saída do stdout para coincidir com o de stderr para que eu possa enviar mensagens de erro para outros programas sem o intermediário de um arquivo.

Estou ciente da notação 2>&1 , mas que combina stdout e stderr em um único stream.

O que eu estou pensando seria algo assim:

 program.exe 2>&1 | find " " 

Mas isso combina stdout e stderr como:

 program.exe | find " " 2>&1 

Eu percebo que eu poderia fazer …

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

Mas isso não tem a flexibilidade e o poder de um program | find " " program | find " " espécie de notação. Fazer isso requer que o program tenha terminado com sua saída antes que a saída possa ser processada.

Pergunta interessante 🙂

O CMD processa o redirecionamento da esquerda para a direita. Você deseja primeiro redirect 2 (stderr) para & 1 (stdout) e, em seguida, redirect 1 (stdout) para outra coisa. Neste ponto, o stderr ainda será redirecionado para a definição anterior de stdout. O pipe ainda funcionará com a antiga definição de stdout (que agora contém stderr).

Se você não se importa com stdout, então você pode redirect para nul

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

Se você quiser capturar stdout em um arquivo, redirecione para um arquivo

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

Se você ainda quiser ver o stdout no console, mas você quer apenas canalizar o stderr para FIND, então você pode redirect 1 para con:

 program.exe 2>&1 1>con: | find " " 

Observe que há uma diferença sutil entre a definição original de stdout e con :. Por exemplo, cls >con: não limpa a canvas, ela imprime um personagem engraçado na canvas.

É possível realmente trocar stdout e stderr se você usar um terceiro identificador de arquivo (inicialmente não utilizado). 1 e 3 conterão a definição original de stderr e 2 conterão a definição original de stdout.

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

Na verdade, existe um identificador de arquivo adicional definido toda vez que um redirecionamento é executado. A definição original é salva no primeiro identificador de arquivo não usado disponível. Suponha que não houve nenhum redirecionamento antes de emitir o comando acima. 3>&2 não salva a definição original de 3 porque 3 não foi definido anteriormente. Mas 2>&1 salva a definição original de stderr em 4 (3 já foi usada), e 1>&2 salva a definição original de stdout em 5.

Então, tecnicamente, o redirecionamento explícito de 3 não é necessário para trocar stderr e stdout

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

2>&1 salva stderr em 3 e 2 é redirecionado para & 1 (stdout). 1>&3 salva stdout em 4 e 1 é redirecionado para & 3 (stderr).

Mas o acima só funcionará corretamente se você tiver certeza de que 3 ainda não foi definido antes de emitir o comando. É muito mais seguro definir explicitamente 3 como no meu exemplo de código anterior.

Por que o meu redirecionamento stderr não termina depois que o comando é concluído? E como faço para corrigir isso? para algumas aventuras realmente selvagens com redirecionamento 🙂

Olhando para http://support.microsoft.com/kb/110930 , parece que você quer 2>&1 1>NUL . Então, algo como o seguinte deve funcionar para você:

 test.exe 2>&1 1>NUL | find "someErrorString"