729

I'm trying to redirect all output (stdout + stderr) of a DOS command to a single file:

C:\>dir 1> a.txt 2> a.txt
The process cannot access the file because it is being used by another process.

Is it possible, or should I just redirect to two separate files?

davidism
  • 98,508
  • 22
  • 317
  • 288
ripper234
  • 202,011
  • 255
  • 600
  • 878

7 Answers7

1154

You want:

dir > a.txt 2>&1

The syntax 2>&1 will redirect 2 (stderr) to 1 (stdout). You can also hide messages by redirecting to NUL, more explanation and examples on MSDN.

Abel
  • 52,738
  • 19
  • 137
  • 227
Anders Lindahl
  • 38,350
  • 8
  • 81
  • 88
  • 35
    thanks for this, didn't know that this unix shell syntax works for DOS too! – chaindriver Aug 14 '12 at 17:00
  • 22
    this is great for hiding all output.. `net stop w3svc >NUL 2>&1`.. thanks! – kodybrown Apr 04 '13 at 17:55
  • 4
    @wasatchwizard Ithink I had trouble with that, but >NUL 2>NUL worked fine – FrinkTheBrave Aug 04 '14 at 08:24
  • 13
    If there is a Handle, there cannot be a space between the Handle (i.e. 2) and the redirect operator (i.e. >). Therefore `2> 2.txt` works (or `2> &1`) `2 > 2.txt` does not; `2 > &1` does not. – The Red Pea Apr 03 '15 at 21:41
  • 13
    I love SO so much. "Ugh, this little one-off problem is going to take like an hour". It took me longer to type this comment than it did to find this answer. – Brandon Aug 02 '16 at 19:25
  • 2
    it's such a shame that microsoft doesn't have a native tee – JJS Oct 24 '16 at 17:19
  • if you want to append, use >> instead of > i.e. dir >> a.txt 2>&1 it is very useful for system logs and exeptions. – Alireza Dec 05 '17 at 06:40
  • Perhaps add some information as per [DelboyJays answer's](https://stackoverflow.com/questions/1420965/redirect-windows-cmd-stdout-and-stderr-to-a-single-file/16713357#16713357) *after* note? – Peter Mortensen Sep 04 '18 at 13:34
207

Anders Lindahl's answer is correct, but it should be noted that if you are redirecting stdout to a file and want to redirect stderr as well then you MUST ensure that 2>&1 is specified AFTER the 1> redirect, otherwise it will not work.

REM *** WARNING: THIS WILL NOT REDIRECT STDERR TO STDOUT ****
dir 2>&1 > a.txt
S.S. Anne
  • 13,819
  • 7
  • 31
  • 62
DelboyJay
  • 2,441
  • 1
  • 11
  • 14
  • 11
    AFTER is what cost me hours to figure out what's wrong DelboyJay! Thank you! – Nam G VU Dec 20 '13 at 07:10
  • 4
    Is it explaned anywhere why putting 2>&1 before 1> will not achieved the intended effect? I strongly suspect this has got to do with the way "cmd" parses commands that gives two different meanings depending on the order in which you specify the redirection. But are the semantic rules documented anywhere because I reckon this is something worthwhile to learn as it could waste hours. – igbgotiz Jul 14 '14 at 22:09
  • 12
    @igbgotiz 2>&1 means 'redirect stream 2 to stream 1'. So you need to set up stream 1 first – FrinkTheBrave Aug 04 '14 at 08:31
  • 3
    @FrinkTheBrave but stream 1 is standard output (e.g. console) if not explicitly specified. That still does not explain it imho. – MarioDS Nov 03 '15 at 12:04
  • 1
    @MDeSchaepmeester, if you do `dir 2>&1 > a.txt`, you're first redirecting (`>`) stream 2 (stderr) to stream 1 (stdout). Then, after both of them are already joined together, you're redirecting stdout (`>` with no specifier) to the file. If you want stderr to go somewhere else, you can't join it with stdout first. – cp.engr Feb 03 '16 at 01:07
  • @cp.engr that still explains nothing because then the rational question: why does it work this way in pretty much every other shell, i.e. sh, zsh, bash, etc. – Hi-Angel Oct 18 '16 at 13:22
  • @cp.engr I replied to your explanation for why redirection to a file in cmd shell should be before redirection of stderr → stdout. – Hi-Angel Oct 18 '16 at 14:02
  • @Hi-Angel I see that. You asked "why does *it* work *this way* in pretty much every other shell...?", suggesting that there are contexts where my explanation does not apply. I don't know what you're talking about. So again, why does *what* work *what way*? – cp.engr Oct 18 '16 at 14:05
  • @cp.engr I mean that in every other shell I know of, it's allowed to set redirection to a file after stderr → stdout to redirect both of them. – Hi-Angel Oct 18 '16 at 14:18
  • 1
    The usual way to do that is to use `tee` which allows something to go to a file, and still go to stdout/stderr. If you redirect a stream, it doesn't still go to the original destination. It's been redirected. – Tim S. Jun 20 '17 at 14:31
  • Good additional info regarding `append` instead of `create` (use >>). – Timo Aug 17 '17 at 12:52
  • In case of appending to log, is it necessary to use `>>` only for the stdout redirection or also for `2>&1`, so that it will be like `2>>&1` ? – Roland Pihlakas Oct 21 '18 at 21:54
  • maybe a simple way to understand this is 2>&1 dups the stream. So if you dup it before 1 is redirected, you're pointing to a copy of the original output location. If you dup it after, you're point to a copy of the new location. – Rick Berge Aug 16 '19 at 15:10
  • 1
    This "do not do this" answer is not an answer. It should have been a comment on the top rated answer. – Nathan Nov 30 '20 at 16:44
85

Background info from MSKB

While the accepted answer to this question is correct, it really doesn't do much to explain why it works, and since the syntax is not immediately clear I did a quick google to find out what was actually going on. In the hopes that this information is helpful to others, I'm posting it here.

Taken from MS Support KB 110930.


From MSKB110930

Redirecting Error Messages from Command Prompt: STDERR/STDOUT

Summary

When redirecting output from an application using the '>' symbol, error messages still print to the screen. This is because error messages are often sent to the Standard Error stream instead of the Standard Out stream.

Output from a console (Command Prompt) application or command is often sent to two separate streams. The regular output is sent to Standard Out (STDOUT) and the error messages are sent to Standard Error (STDERR). When you redirect console output using the ">" symbol, you are only redirecting STDOUT. In order to redirect STDERR you have to specify '2>' for the redirection symbol. This selects the second output stream which is STDERR.

Example

The command dir file.xxx (where file.xxx does not exist) will display the following output:

Volume in drive F is Candy Cane Volume Serial Number is 34EC-0876

File Not Found

If you redirect the output to the NUL device using dir file.xxx > nul, you will still see the error message part of the output, like this:

File Not Found

To redirect (only) the error message to NUL, use the following command:

dir file.xxx 2> nul

Or, you can redirect the output to one place, and the errors to another.

dir file.xxx > output.msg 2> output.err

You can print the errors and standard output to a single file by using the "&1" command to redirect the output for STDERR to STDOUT and then sending the output from STDOUT to a file:

dir file.xxx 1> output.msg 2>&1
StackzOfZtuff
  • 1,671
  • 18
  • 19
StormeHawke
  • 5,534
  • 5
  • 38
  • 68
32

To add the stdout and stderr to the general logfile of a script:

dir >> a.txt 2>&1
Henk Wiersema
  • 439
  • 4
  • 5
13

Correct, file handle 1 for the process is STDOUT, redirected by the 1> or by > (1 can be omitted, by convention, the command interpreter [cmd.exe] knows to handle that). File handle 2 is STDERR, redirected by 2>.

Note that if you're using these to make log files, then unless you're sending the outut to _uniquely_named_ (eg date-and-time-stamped) log files, then if you run the same process twice, the redirected will overwrite (replace) the previous log file.

The >> (for either STDOUT or STDERR) will APPEND not REPLACE the file. So you get a cumulative logfile, showwing the results from all runs of the process - typically more useful.

Happy trails...

falsetru
  • 314,667
  • 49
  • 610
  • 551
Max Vitesse
  • 131
  • 1
  • 2
3

There is, however, no guarantee that the output of SDTOUT and STDERR are interweaved line-by-line in timely order, using the POSIX redirect merge syntax.

If an application uses buffered output, it may happen that the text of one stream is inserted in the other at a buffer boundary, which may appear in the middle of a text line.

A dedicated console output logger (I.e. the "StdOut/StdErr Logger" by 'LoRd MuldeR') may be more reliable for such a task.

See: MuldeR's OpenSource Projects

LigH
  • 31
  • 4
1

In a batch file (Windows 7 and above) I found this method most reliable

Call :logging >"C:\Temp\NAME_Your_Log_File.txt" 2>&1
:logging
TITLE "Logging Commands"
ECHO "Read this output in your log file"
ECHO ..
Prompt $_
COLOR 0F

Obviously, use whatever commands you want and the output will be directed to the text file. Using this method is reliable HOWEVER there is NO output on the screen.

PanamaPHat
  • 11
  • 2
  • 1
    (basically the same answer given a few times years ago.) You can force output to screen with `>con echo This goes to screen` Also useful for user input `>con set /p "var="Input: "` Note: those lines will *only* appear on screen and *not* be redirected to the file. – Stephan Sep 14 '19 at 08:21