Dado que o CMD.EXE está insuficientemente documentado, não sei qual deve ser o comportamento esperado. Eu certamente não vi nenhuma documentação sobre qual é o comportamento esperado. Então, acho que você será duramente pressionado para encontrar alguém que possa dar uma resposta definitiva sobre se algum dos comportamentos é um bug. Mas eu concordo que certamente é inconsistente, e parece pelo menos uma falha de design para mim.
Eu não caracterizaria a situação como caótica, pois o comportamento de um determinado comando parece ser reproduzível. Mas o CMD.EXE é inconsistente, pois não consigo prever como qualquer comando se comporta sem testar.
Eu não tenho explicações, mas tenho algumas classificações refinadas de comportamentos.
O redirecionamento de stdout ou stderr para stdin funciona perfeitamente, contanto que nenhum comando realmente tente escrever qualquer coisa na saída redirecionada. O comportamento estranho só ocorre quando um comando interno tenta gravar em stdout ou stderr depois de ter sido redirecionado para stdin.
Eu estendi seus testes e vi os seguintes comportamentos distintos:
STDERR redirecionado 2>&01
Eu não fiz testes exaustivos, mas todo comando interno que testei e grava em stderr terminará imediatamente a sessão de comando se stderr for redirecionado para stdin. Exemplos incluem:
cd invalidPath 2>&0
vol x 2>&0
copy nonExistentFile 2>&0
move nonExistentFile 2>&0
set nonExistentVariable 2>&0
dir nonExistentFile 2>&0
O que você achava que era uma exceção, na verdade nunca grava em stderr. Tente o seguinte sem redirecionamento e você verá que não há mensagem de erro:
dir nonExistentFIle *
Portanto, não há razão para o comando encerrar a sessão de comando se o stderr for redirecionado para stdin.
O DIR imprime apenas uma mensagem de erro se não encontrar nenhum arquivo correspondente em todas as máscaras de arquivo fornecidas.
:: This prints an error message
dir nonExistentFile1 nonExistentFile2
:: So this terminates the command session
dir nonExistentFile1 nonExistentFile2 2>&0
Redirecionado STDOUT 1>&0
Aqui estão os comportamentos que vi para a stdout redirecionada:
1) A saída desaparece no éter, sem qualquer mensagem de erro.
Exemplos:
vol >&0
copy /-y file1 existingFile2 >&0
move /-y file1 existingFile2 >&0
2) A saída falha e uma mensagem de erro é exibida para stderr. Um único comando pode gerar várias mensagens de falha, uma para cada tentativa malsucedida de gravar no stdout.
Exemplos:
cd >&0
echo Hello >&0
:: This generates 2 error messages, one for the time,
:: and another for the subsequent empty line
time /t >&0
3) A saída falha e o processamento em lote é finalizado. SETLOCAL ativo permanece em vigor, mesmo após o término do lote, se o erro ocorrer dentro de uma sub-rotina chamada. A este respeito, comporta-se muito como um erro de sintaxe fatal.
Até agora, só vi um comando exibir esse comportamento:
dir >&0
Espero que o comando DIR gere uma mensagem de erro para cada linha de saída tentada. Mas parece terminar depois de falhar na primeira linha, e o processamento em lote também é abortado.
4) Alguns comandos exibem vários comportamentos.
Exemplos:
:: This SET command generates an error message for each
:: defined variable (behavior 2)
set >&0
:: But this SET command fails to display the prompt without
:: error message (behavior 1). Note that the echo of user input
:: is written directly to :con. It does not use stdout or stderr.
set "var=prompt" >&0
:: A single PAUSE exhibits both behaviors 1 and 2. The prompt to
:: press a key simply dissapears, and the echo of the user input
:: generates an error. Note that in this case, the echo of user
:: input is written to stdout.
pause >&0