Redirecting Output to a File in Windows Batch Scripts

Microsoft’s Command Redirection Operators page provides the factual information on how to do redirection, but actual implementation gets a bit confusing for anything beyond command > filename.txt. Here’s a rundown on how to do some useful things. I’m not going to cover every aspect of redirection, but I’ll point you to the cases I find myself in most often.

The basics. You want to generate either a log file or a file that you will be executing after you’re done generating it. You’ll likely be using a combination of echo commands as well as some output from a handful of commands. Welcome to the > and >> operators. The first will send the output to a file and erase its existing contents; the second will append the output to the file.

Examples:

# This will send the dir command’s output to a fresh file:
dir > myfile.txt

# Here I will create a fresh file with an echo command,
# and append the dir output to that:
echo Here is a directory > myfile.txt
dir >> myfile.txt

Redirection for logging. This is a great way to make log files, which can even have the date and time with a simple improvement over that last example:

echo %date%, %time%: Listing a directory. > myfile.txt
dir >> myfile.txt

Using this technique, you can log not just what your batch scripts are trying to do, but what the results are. For instance, let’s say we’re generating a batch script that automatically creates accounts and drops them in a group. If I’m doing this in AD, I might have code like this:

# Add user “joe” to the “MyGroup” group.
net group MyGroup joe /add

To log the result of this, I might try:

net group MyGroup joe /add >> AddAccts.log

Better error logging. When this command succeeds, it outputs, “This command completed successfully.” It will output this to the log file, and you know the net group command succeeded. However, if there were errors, it will output, “The command completed with one or more errors.” However, the standard output doesn’t include the actual error messages, even though you can see them outputting to the screen. This is because there is a separate error stream, and by default, the redirection operator only streams the standard output.

This is where the >& operator comes in. This will pass the output from one “stream”, or “handle” into another. This means you can take a command’s error stream, and pass it into its output stream, so that both standard output and error output will be together.

Everything thus far was in Microsoft’s documentation page I referred to earlier. But now how do you use the >& operator? I stumbled across Eric Jarvi’s blog post, “Redirecting stderr to stdout on the command line“, which has an example in the comments.

A quick preface: The standard output stream has a handle of 1, and the error stream has a handle of 2. That being said, take the above example, and modify it like this so that both stdout and stderr will stream to your file:

net group MyGroup joe /add 1>>AddAccts.log 2>&1

This code is effectively saying: “Perform the net group command, then output the stdout to AddAccts.log, but also redirect the stderr stream into the stdout stream at the same time.”

As a result, you have stdout and stderr both in your file. Your log will now give you much more meaningful feedback on any errors your batch scripts might be encountering.

What about combining stdout and stderr when piping? It may not be readily apparent, but you can also accomplish this with the 2>&1 redirection. It’s just important where you place it; the redirection must occur before the pipe. So something like this would do the trick:

mycmd 2>&1 | othercmd

This would properly send both stdout and stderr from “mycmd” into the stdin stream for “othercmd”.

I find the above operators the most commonly used in my development. I hope you found this information useful.

53 Responses to “Redirecting Output to a File in Windows Batch Scripts”

  1. Mark Says:

    Fantastic - EXACTLY what I was after, found it via Google. Thank you. :-)

  2. Josh Says:

    I’m glad it was helpful!!

  3. Bill Says:

    Wow! Exactly what I needed! Redirecting standard error will help a lot! Found you via Google.

  4. Robbie Says:

    Thanks!!! Awesome

  5. mtdman Says:

    Ditto Mark and Bill’s comments. Thanks!

  6. Matt Van Stone Says:

    Another thanks here.

    Found you through Google.

  7. Richard Says:

    And to think, other articles I have read say that this is impossible!

    Thanks Josh

  8. Brian Says:

    Much appreciated. This is exactly what I needed to debug a tricky problem in my CVS server scripts.

  9. Arun Says:

    Batch File output Redirection:

    I want to redirect the output of my batch file to a .txt/.doc/.xls file.

    For that I am using the syntax:

    “C:\ProjFolder\Application.exe > Logfile.txt” and saved it as a batch file.

    My Log file is supposed to hold several 1000 lines of data.

    But my problem is that after certain limit, no data is going into the Logfile.

    Somebody please tell me the reason???

  10. Munish Says:

    Thanks all, helped me a lot. This was exactly i was looking for.

  11. manoj Says:

    Thanks for the tip.

  12. Rick Lim Says:

    Thanks for this tutorial. I had been wondering how to do that until i read this.

  13. Eugenny Says:

    Thanks :) That was REALLY helpful!

    Usual redirect was not working for me, so thank You one more time. Also found this article via google.

  14. atroon Says:

    Thanks! You’re a lifesaver. Well, so is Google. But this is exactly what I was looking for.

  15. Mathieu Says:

    Thank you very much, I have been looking for this for many many hours.

  16. Jeff Says:

    Thanks! Coming from the unix world, I didn’t know if the stdout/stderr applied in Windows. This was reassuring. Used this in windows task scheduler to redirect the logs to someplace meaningful, and added the YYYYMMDD date to make it easy to find:

    C:\script.cmd > C:\Logs\script.%date:~-4%%date:~4,2%%date:~7,2%.log 2>&1

  17. sandeep verma Says:

    greate very helpfull

  18. Ox Says:

    Doesn’t ‘net group MyGroup joe /add 1>>AddAccts.log 2>&1′ also direct standard input to a file ? My concern is how does one terminate a batch file in such a case. Pardon me for my noobieness : (
    I am trying to avoid a dual batch file situation.

  19. Ox Says:

    My bad - I had put a pause instead of an exit at the end of my batch file.. :0

  20. Lutecki Says:

    Great job :)

  21. DutchUncle Says:

    Sorry, this works just as expected if I type the command in a command window, but the same command cut-and-pasted into a batch file does not work. The output file is created, but the program’s output is written to the screen and the file is empty. I also note that the “echo” of the batch file line adds the “1″ stdout file handle to the line. Any clues?

  22. Josh Says:

    DutchUncle, that doesn’t sound right. Be sure you don’t have any extra spaces where they don’t belong. For instance, a space between the 1 and the >> would cause the behavior you described.

    Also, my scripts that are in production are indeed ran from a batch file and work ok. Be sure too that your text editor isn’t adding carriage returns from word-wrapping or something similar.

  23. DutchUncle Says:

    My error. Well, really Microsoft’s error, but at a much more interesting level. Without intending to, I left out an important item: The batch file with the line with the redirection is invoked from within another program.

    Going through the whole process to see where I messed up, I tried the commands in a command window; then built up a batch file and invoked it from the command line, and it *did* work as expected. Then I went into my compiler IDE and put a line like
    cmd call foo.bat
    in the “post-build” command slot. It invokes the batch file just fine, and performs multiple steps that can be traced, but the stdout and stderr must be captured by the subprocess activation instead of being handled at the level that can be redirected.

    By the way - I’ve been doing things like this in batch files since DOS. And the concepts go back to CP/M.

  24. Josh Says:

    Ah, interesting. I’m not surprised that the “shell” that the batch script executes in while in the scope of the other app does behave differently. I have executed scripts from within ColdFusion scripts and observed similar behavior where the application server grabs ahold of the output.

    Thanks for that followup, DutchUncle. And no insult intended by the simplistic response. Sometimes it can be difficult to gauge the level of expertise from an initial comment. :-)

  25. Moe Says:

    Is there a way to create a file with a Batch file that contains the Date in the file name?

  26. Moe Says:

    Sorry what I meant was after I created a file using the date switch. (which works fine thatnk you) How can I append to it? It appears that nothign gets added using the >> switch.

  27. Sarathy Says:

    Thanks, it is very informative

  28. Ashish Says:

    Exactly what I was looking for. Found you thru google. Thanks a lot!

  29. Joshua Curtiss Says:

    Moe, an easy mistake to make is to use one > the first time in your batch script and >> everytime thereafter. That’s the way to go if you want to build a new file every time. But if you want a running log that survives all script runs over time, every time you redirect to the file you want to use >>. Note that this operator, which appends the content to the file, still works to create the file if it doesn’t exist.

    I hope this answers your question. I wasn’t quite following you.

  30. DanaBrigham Says:

    Thanks — the combo of stderr and stdout is a good thing!

    I still find some commands where stderr and stdout go to the screen, even with this redirection — the “REG” command for editing the Registry from the command line is a good example. Any idea why? And how to force it to output to a log?

    Dana

  31. SenHu Says:

    Hi. Excellent article, and a great discussion following it.

    Do take a look at biterscripting. It offers much more control over stdout and stderr. For example, you can redirect these to/from variables, inline commands, files, etc. Often times, when I need to precisely control the stdout, stderr of a DOS command, I call it thru biterscripting, as follows.

    system “some command, switches, arguments” > $out > $err

    ($out, $err are declared as string variables.)

    Another thing, their echo command provides an option -e, which writes to stderr instead of stdout. I use that for debugging. For example

    echo -e “DEBUG Time=” gettime()

    The above will write “DEBUG TIME=20090405163010″ to the stderr. This way, when I am done debugging the script, I call it as follows.

    script “some script” 2>null

    The above stops outputing of the DEBUG messages without making any changes in the code for that script.

    Sen

    (You can download biterscripting free from http://www.biterscripting.com . Install all their sample scripts, which are an excellent starting point, with the following command.

    script “http://www.biterscripting.com/Download/SS_AllSamples.txt”

    biterscripting can execute scripts directly form a web site.)

  32. SenHu Says:

    Forgot to mention about the REG command. To force its output to a log file, call it from biterscripting as follows.

    system reg “options, arguments …” >> output.log >> error.log

    The above will force the output and stderr to go to files output.log and error.log respectively.

    Sen

  33. Thom Says:

    What about piping both the stdout and stderr of a program into the stdin of another program? It doesn’t look like the “&” works the same way when attached to a “|” instead of a “>”.

  34. Josh Says:

    You can still redirect the error stream into the standard output, and the redirection will be properly piped into the other program.

    Something like this:

    mycmd 2>&1 | othercmd

    This will combine the stdout and stderr streams from “mycmd” and pipe them into the stdin stream for “othercmd”.

    Thanks for the very good question!! I’m going to append a note about this to the blog post.

  35. GuidoDG Says:

    Hi, I also have a question about redirection. I wanted to have both STDOUT and STDERR of an xcopy sequence into a logfile. So far no problem but i use the /-Y option which sometimes requires some user interaction. This is a bit dificult without that the question comes on the screen… So i actually want the output both on the screen as in the logfile. Although Microsoft talks a lot about ‘duplicate’ handles when using the syntax >&, i do not see any duplication, just redirection. For the moment I only redirect the error stream to a file and then i readout the last line of that file to get it on the screen as well… Not exactly elegant, perhaps somebody knows how to redirect to multiple output ? Guido.

  36. rustylee Says:

    Great article! Got me out a jam.

  37. Josh Says:

    GuidoDG, I believe it is not possible to have the output go to console and to a file with built in functionality. However, there are command line stream splitters like MTEE that would probably help you accomplish your goal. I haven’t used this app, but it appears free, relatively easy to use, and simple to deploy (no installation process required). Just plop it on your system and start using it.

    If you use this app and it works great for you, leave a comment to let us know!

  38. GuidoDG Says:

    Hi Josh, thanks a lot for this tip. I tried it out and it works perfectly. With 1 line
    xcopy %source% %destination% %options% 2<&1 | mtee /+ xcpy.log
    both STDERR and STDOUT appear as well on the screen as in the logfile. Thanks, Guido.

  39. karel Says:

    Thanks - this kind of stdout, stderr redirection is was i looked after. Tee on win32 is also a dream that came true :)

  40. JM Says:

    Very well explained. Thnx Josh.

  41. Denys Says:

    So easy with mtee. I have been lookong for this for sooooo long. Thanks to all.

  42. Michael Says:

    Thanks for the info. I tried using mtee to send output to both the console and a log file, simultaneously - but there seems to be a significant delay sending the output to the console. It’s bursty. Is there any way to flush the console output so it is displayed closer to real-time?

    thanks

  43. John Says:

    Thanks very much. This was exactly what I was looking for when trying to log Python unit test output in a Django project to a file.

    Normally, part of the output goes to stdout and part to stderr, so not everything makes it to the file. With this, everything goes to the file.

    Found via Google. Keep up the great posts.

  44. links for 2009-07-22 | Nathan and his Open Ideals Says:

    […] Cranky Bit » Redirecting Output to a File in Windows Batch Scripts mycmd 2>&1 | othercmd (tags: scripting shell windows programming) Share and Enjoy: […]

  45. johnny Says:

    Hello. Thank you for this great info! Keep up the good job!

  46. Ilya Says:

    Thanks, this is exactly what I was after! Nice Article.

  47. anusha Says:

    Very useful article!! :)

  48. Vaibhav Says:

    It was quiet helpful. Very well explained.
    Thanks !!

  49. SenHu Says:

    Very nice article and discussion.

    In terms of the tee command - there are four pipe combinations possible - one to one, one to many, many to one, many to many. UNIX does provide tee command (T-Pipe) for one to many. But there is no wye command (Y-pipe) for many to one or there is not eh command (H-pipe) for many to many.

    I have been using biterscripting ( http://www.biterscripting.com ) which does something clever - it allows the command’s output to be redirected to a string variable. Using that, the following are examples of all four combinations.

    var str s

    # one-to-one
    lf > $s
    len $s

    # one-to-many
    lf > $s
    len $s
    echo $s

    # many-to-one
    cat x.txt > $s
    cat y.txt >> $s
    echo $s

    # many to many
    cat x.txt > $s
    cat y.txt >> $s
    len $s
    echo $s

    with this, the pipes become unnecessary.

  50. anonymous Says:

    Thanks ! :D

  51. Si Says:

    Thaks a lot Josh! Your article is a gift for me!
    And one step forward is the solution for the commands like REG: reg “options, arguments …” 1>output.txt 2>&1 3>&1 :))
    This does work!!!

  52. Gari Says:

    I need a help.I have to make a DOS batch file. There are two logical files and if some one try to open those files they should get a message saying they don’t have access to this file.
    Can you respond soon?

  53. Pekka Says:

    Thanks a lot!

Leave a Reply

  Theme Brought to you by Directory Journal and Elegant Directory.