4

From a question on Stackoverflow, i've being testing with redirection from/to stdin stream. And this tests, trying to send data to the stdin stream, just to see what happens, end with an apparently chaotic behaviour.

Commands like

echo testing >&0
dir >&0 
cls >&0

will generate a System can not write to the specified device (seems stdin is a read only stream, maybe), but things like

  • vol >&0 does not show any error

  • set /p "var=prompt" >&0 waits for the input while not showing the prompt and not showing any error

  • pause >&0 will wait without any error, but when a key is pressed error is shown

And the last straw is stderr redirection. When using internal commands that send output to stderr with it redirected to stdin, like

call "noFile" 2>&0
dir  "|" 2>&0

the result is that cmd.exe will be closed. But not always. Things like

dir "|" * 2>&0
dir * "|" 2>&0

work without problems, hiding the text sent to stderr and printing the rest of the information.

So, the question is, is this a bug, is it documented somewhere and i am unable to find it or is this the expected behaviour and there is something obvious that i am missing?

0

3 Answers 3

4

Given that CMD.EXE is woefully under-documented, I'm not sure what the expected behavior should be. I certainly haven't seen any documentation as to what the expected behavior is. So I think you will be hard pressed to find anyone that could give a definitive answer as to whether any of the behaviors are a bug. But I agree it certainly is inconsistent, and seems like at least a design flaw to me.

I wouldn't characterize the situation as chaotic in that the behavior of a particular command seems to be reproducible. But CMD.EXE is inconsistent in that I can't see any way to predict how any one command behaves without testing.

I don't have any explanations, but I do have some refined classifications of behaviors.

Redirection of stdout or stderr to stdin works perfectly fine as long as no command actually tries to write anything to the redirected output. The strange behavior only occurs when an internal command attempts to write to stdout or stderr after it has been redirected to stdin.

I extended your tests, and have seen the following distinct behaviors:

Redirected STDERR 2>&01

I haven't done exhaustive testing, but every internal command I tested that writes to stderr will immediately terminate the command session if stderr has been redirected to stdin. Examples include:

cd invalidPath 2>&0
vol x 2>&0
copy nonExistentFile 2>&0
move nonExistentFile 2>&0
set nonExistentVariable 2>&0
dir nonExistentFile 2>&0

What you thought was an exception actually never writes to stderr. Try the following without redirection and you will see there is no error message:

dir nonExistentFIle *

So there is no reason for the command to terminate the command session if stderr is redirected to stdin.

DIR only prints an error message if it fails to find any matching file across all the supplied file masks.

:: This prints an error message
dir nonExistentFile1 nonExistentFile2

:: So this terminates the command session
dir nonExistentFile1 nonExistentFile2 2>&0


Redirected STDOUT 1>&0

Here are the behaviors I have seen for redirected stdout:

1) The output dissapears into the ether, without any error message.

Examples:

vol >&0
copy /-y file1 existingFile2 >&0
move /-y file1 existingFile2 >&0


2) The output fails and an error message is displayed to stderr. A single command can generate multiple failure messages, one for each failed attempt to write to stdout.

Examples:

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) The output fails, and batch processing is terminated. Active SETLOCAL remain in effect, even after batch termination, if the error occurs within a CALLed subroutine. In this regard, it behaves much like a fatal syntax error.

So far I have only seen one command exhibit this behavior:

dir >&0

I would expect the DIR command to generate an error message for each attempted line of output. But it seems to terminate after failing on the first line, and batch processing also is aborted.


4) Some commands exhibit multiple behaviors.

Examples:

:: 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
1
  • Of course. I failed to see the dir command does not write to stderr when something is found. And yes, inconsistent is the precise term, thank you.
    – MC ND
    Sep 1, 2014 at 7:02
0

I first discovered this bug by mistake in 2010. I ultimately discovered my mistake - redirecting stderr to stream 0 (stdin for the current process) makes no logical sense, and cmd.exe did not have a handler for that scenario, so it just bailed out. The correct syntax was:

dir 2> nul (if I only wanted to redirect the error)

or

dir 2>nul 1>&2 (if I also wanted to redirect successful output).

Basically just an unhandled exception in CMD.EXE for any built-in commands. Here's my write-up from a few years ago: http://dnlongen.blogspot.com/2013/05/how-to-crash-windows-shell.html

1
  • Thnk you. This was not an mistake. As you I have sometimes the posibility/time to attach the debugger to something and play. I know (from previous tests) that if the command processor is not able to write to stderr (it shouldn't happen) it directly exits. What I was not seeing is why "sometimes" it didn't happen. As dbenham pointed what I was not seeing is that my "problematic" cases were not writting to stderr.
    – MC ND
    May 21, 2015 at 14:36
0

Take a look at https://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr=true (archived)

>& Writes the output from one handle to the input of another handle.
<& Reads the input from one handle and writes it to the output of another handle.

The & redirection operator duplicates output or input from one specified handle to another specified handle. When you duplicate a handle, you duplicate all characteristics of the original occurrence of the handle. For example, if a handle has write-only access, all duplicates of that handle have write-only access. You cannot duplicate a handle with read-only access into a handle with write-only access.

2
  • Please read the question again carefully. Your answer does not answer the original question. You make no attempt to explain any of the strange behaviours in the OP's question. Please read the accepted answer to see what a good answer looks like.
    – DavidPostill
    Apr 21, 2016 at 12:24
  • Oops my fault, you're right: my answer does not explain why sometimes returns error and sometimes doesn't or crash. It points that should always return error (the "cannot write...") as expected behaviour so it seems a bug as @David-Longenecker says below and explains in his blog dnlongen.blogspot.com/2013/05/how-to-crash-windows-shell.html
    – joanmib
    Apr 23, 2016 at 9:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .