cmd.exe redirection operators order and position

First about order

The following works to redirect stdout and strerr to nul.

command 1>nul 2>&1

The following doesn't

command 2>&1 1>nul

Why does the order matter? How could these expression be read in a human understandable language?

About position

This works

command 1>nul 2>&1

and this too

1>nul 2>&1 command

Why? Any official reference documentation on syntax rules would be helpful.


Solution 1:

command 2>&1 1>nul doesn't work is not correct. It works. But as usual, it does what you asked not what you wanted

From left to right:

  • 2>&1 data to stream 2 (stderr) will be sent to a copy/duplicate of the handle that stream 1 (stdout) is using.

  • 1>nul data to stream 1 will be sent to nul.

The duplicate is the key. Data is not sent to whatever stream 1 points, but to a copy of the stream handle. When stream 1 is redirected, stream 2 has its own handle, a copy of the previous stream 1. Changing stream 1 does not affect stream 2

Now, lets see the working code, from left to right

  • 1>nul Set the handle in stream 1 to point to nul

  • 2>&1 Set the handle in stream 2 to a copy of the handle in use in stream 1, that is, a handle to nul

About position

Most of the time the position (before command, after command or both) is irrelevant. To execute a command, the parser has to first prepare the streams that the command will use. This preparation is done if it is considered necessary (try redirecting rem command input or output) before starting command execution.

The only cases where there is a difference are when what we want to obtain from the command and what the parser understands are not the same. One obvious case is when we need to output a string with an ending digit. Code as

echo 1 2 3>file 

will not send the full string to the target file. 1 2 will be echoed to console, and the data written to stream 3 (nothing in this command) will be sent to file

Of course, a space can be added at the end of the data (between 3 and >), but this space will be included in the output. If this is not acceptable, the solution is to place the redirection at the start of the command

>file echo 1 2 3

Solution 2:

CMD simply emulates command.com from MSDOS 5. The extra facilities added were applied as a "shell", encapsulating existing functionality and quirks to ensure that existing batches would suffer the least impact.

There are many incomprehensible decisions made by the developer(s). It seems to be a low-priority badly-supervised project, as evidenced by the poor and inconsistent spelling in the inbuilt documentation, the decision to have a leading-zero string interpreted as Octal not decimal, rather than using O'123' analogous to H'123' for hex. There's no /u switch for universal-date-format in the date/time utilities and dozens of other quirks requiring workarounds - all of which point to a poorly-supervised project given to a cavalier developer unblooded in the realities of commercial programming.

So - the 2&1 syntax is an add-on applied poorly to a product that it was hoped would fade away under pressure from the point-click-and-giggle generation. Consequently, it's not "industrial-strength" - yet ironically has survived for all that.

The fact that there has been little further development over the last decade or more shows its "poor cousin" status. There's no money in it because it's not flashy and by being backward-compatible, it's bound to thinking rooted ultimately in the 1950's.

Consequently, there's no commercial reason for the anomalies introduced by the post-DOS5 improvements to be resolved. The sequence problem came along because of the programmer's mindset, not considering that anyone would try to use the new facilities in any other way than seemed logical to that particular programmer.

Hence, you use the redirection in the manner in which that programmer decided you should, and there's no prospect of having that changed anytime soon - unless you can come up with a few million to finance the development of what you want, I'd expect.