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.

What about sending just stderr? This is simple. Take a look at Redirecting Errors to a File in Windows Batch Scripts for a quick post on doing that.

92 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!

  54. Methodenmann Says:

    Das hab ich kommen sehen ^^ :p Tollen Tag!

  55. Rudy Says:

    Does anyone know how to capture output when the command is: start /separate xcopy %source% %destination% >>output1.txt

    I have a batch file that run multiple xcopy commands (to copy files from different locations). I don’t want the commands to run sequentially but concurrently, and I like to capture their outputs. thanks.

  56. Noor Says:

    Rudy did you try hstart. It is similar to background in unix/linux.

  57. Rudy Says:

    Hi Noor, that would have worked; however, it says it will run the specified apps synchronously. I like the run in the background option though. thanks.

  58. Max Says:

    Thanks.

    Note, to get this working in task scheduler (at least in Win 2008 Server) I had to run using cmd.exe /c, like this:
    cmd.exe /c myexe.exe >> logfile.txt

  59. Danny Seager Says:

    Not exactly the same topic but similar and there are clearly some very knowledgable people here…

    I have a bat file which performs an ftp upload (well holds the commands), this works great from either the cmd prompt or shelling out from my application. The command I use is

    FTP -n -s:C:\Script.txt

    I want to log the results of this so I can ensure the file was properly uploaded… so I change the command to

    FTP -n -s:C:\Script.txt >> C:\Test.log

    and this works great from the cmd prompt… but not from the shell command… the dos window flicks up and then closes again…. So I thought I would just create a bat file to do this…. so I paste the code into a bat file and try that from the cmd prompt but the command doesn’t seem to do anything but the same command is being written to the log file constantly which makes it grow pretty quick.

    Any ideas anyone?
    Thanks

  60. Ampoule led Says:

    thanks for the post mate

  61. SenHu Says:

    For FTP uploading files via a batch script, take a look at this script.

    http://www.biterscripting.com/helppages/SS_FTPUpload.html

    It upload files via FTP, also captures output and errors in files.

  62. Arun Praksh Says:

    thanx man nice article

  63. Vasanth Says:

    very usefull one.Thanks for sharing it with us.

  64. Sunil Says:

    Thanks – I found the information what I am looking for.

  65. Mark Says:

    How do you pipe STDERR _without_ joining it with STDOUT?

  66. Josh Says:

    Mark, good question. Here’s the answer on this post: Redirecting Errors to a File in Windows Batch Scripts.

  67. vani Says:

    Hey, I’m completely new at this and I was wondering if there is a way that I would be able to redirect the log files in a directories standard output and standard error into and excel spreadsheet in anyway?

    Please remember don’t use too advanced of terminology as I just started using shell scripts yesterday for the first time.

    Thank you!

  68. Jason Says:

    Thank you sooo much for this! Apparently ffprobe (info about mpeg files) only outputs to stderr, was driving me crazy when I couldn’t figure out why I couldn’t direct ouput to a file! :)

  69. Josh Says:

    Interesting. Glad it helped!

  70. arun Says:

    Could you give an idea how I could redirect output log to a new file every time I run a batch script
    Regards

  71. z bolt Says:

    It gave me a good start. But, is there a way to echo output to the screen and also to the file?
    Basically, my batch file lets prints messages on console and lets user enter Y/N options and does some stuff. I want to capture all the messages and user’s input plus the stdout of commands executed in the batch file. Is it possible?
    Thanks for the article!!

  72. GuidoDG Says:

    Hi Bolt, I had the same question. See the comments starting from 22 April 2009 for the solution. Regards.

  73. Josh Says:

    @Guido, right, thanks for pointing him to that. I’m glad this page is turning out to be useful for many people.

  74. Satish Says:

    helpful indeed , Thanx Folks

  75. John Says:

    have tried the above (not http://www.biterscripting.com/) and have an issue, which i suspect is with the application. I am creating a diagnostic script using WINDUMP to capture FTP traffic for testing servers.
    I want to get the NIC device so that I can then set a variable to it, then use it to enable WINDUMP logging. I have tried the following command line (hybrid bash script run at CMD):
    windump -d | grep Device > \temp\x 2>&1
    windump: listening on \Device\NPF_{AAAAAAAA-27B3-0000-A8D8-EA0F6634C14A}

    I want to then do DOS for loop, parse the above from \temp\x and get the device name.

    the message is put on the screen, but I doubt it is going to STDOUT or STDERR. the \temp\x file is empty. I suspect it is writing to an non standard channel.

    any ideas?

  76. Adam Says:

    Hi there. I seem to have taken a wrong turn trying to implemend this and have got myself into a real bind. I created a simple script to run defrag.exe and pipe results to a logfile. So far so good. I then looked for ways to optionally display the output instead of piping to logfile, and this seemed to work. I changed the script as per below, and it worked but got “2>&1 unexpected at this point” at the end of the script. No biggie, only now when I run *any* script, it churns out output from my defrag script. Any thoughts on where I went wrong, and how to fix it?

    Many thanks,
    Adam

    @echo off
    :: Defrag script

    c:
    cd \

    set output=c:\_scripts\defrag.log
    if “%1″ == “con” set output=con

    echo Defragging your hard drive, please allow to run..
    echo. >> %output%
    echo ——————————————————— >> %output%
    echo Start defrag on %date% at %time% >> %output%
    echo. >> %output%
    echo Defragging C: >> %output%
    echo. >> %output%
    defrag c: -f -v 1>> %output% 2>&1
    echo. >> %output%
    echo Defragging E: >> %output%
    echo. >> %output%
    defrag e: -f -v 1>> %output% 2>&1
    echo. >> %output%
    echo End defrag on %date% at %time% >> %output%
    :end

  77. Adam Says:

    Scratch that. Just worked it out – isn’t it always the way that you realise you did something stupid, right after posting it to the world? :)

  78. Josh Says:

    Haha no worries :-)

  79. please help with linux with redirecting errors and output? | Froggy IT Solutions Says:

    [...] if it works for each command, the way you are trying to do it Add your own answer in the comments!Question by CH: please help with linux with redirecting errors and output? I'm trying to redirect th…d nothing has been placed in x3. When I make other errors nothing is put in x3 and they still show [...]

  80. Seth Wegner Says:

    just what I needed and Found after googling as well. Thanks!

  81. ahmed Says:

    i tried this command:
    -
    echo xcopy /y /e /r /k /h D:\z d:z >D:\log.txt >>copylog.txt
    -
    result on copylog.txt:
    -
    xcopy /y /e /r /k /h D:\z d:z
    -
    i want this for the result on copylog.txt:
    -
    xcopy /y /e /r /k /h D:\z d:z >D:\log.txt
    -

    any ideas?

  82. Tony Says:

    In unix i could begin a script with:
    exec >log.out 2>&1
    This would redirect all output from the scipt to the log file. Is there a way to do this in a bat file? I don’t want to have to put the >log.out 2>&1 after EVERY command in the bat file!

  83. Mark Says:

    What I’m trying to do is very similar but I want to use commandline variable to name the file. What I’m trying to do is something like:

    chkdsk h: > %date%.txt

    But this doesn’t work

    Any Ideas??

  84. Josh Says:

    This is because the plain date command echoes the date in a format that is not file-friendly, such as “Wed 02/08/2012″. When I’m generating a filename based on date, I do something like this:

    %date:~10,4%-%date:~4,2%-%date:~7,2%-%date:~0,3%

    Which would generate something comparable to this: “2012-02-08-Wed” which is friendly for a filename.

    Hope this helps.

  85. Josh Says:

    Tony, I’m not sure but I don’t think Windows provides that kind of encapsulation of the output.

  86. Adrian Says:

    I needed ro run the s script as a batch job, and wanted the ourput and errors, but did not want to redirect ecerything either, so I created a wrapper script, which allowed all output to go to the file, when required.

    @ECHO OFF
    REM==============================================================
    REM XXX_SYSTARTUP.CMD
    REM
    SET mydir=%~DP0
    IF NOT EXIST %mydir%xxx_systartup_win.cmd GOTO :bad_exit
    %mydir%xxx_systartup_win > %mydir%xxx_systartup_win.log 2>&1
    REM
    REM N.B. The called script never returns
    REM
    :bad_exit
    ECHO xxx_systartup.cmd – System Startup Failed >> %mydir%xxx_systartup_win.log
    EXIT /B 2

  87. furqan Says:

    Hi sir I like this site very much and I really appreciat to you for your brelliant job.

  88. jc2it Says:

    Helpful ++

  89. Neo Says:

    Thanks all Its very helpful

  90. Jonh Smith Says:

    THANK YOU!!!
    I spendt literaly hours seaarching for this!
    Still, it was a bit tricky for me, if like me someone is still not getting it (although it is very simple).
    I wanted to make a output with more than one line, here it is the right way, at least worked for me, Im Running Windows 7)

    echo cls>output.txt
    echo @echo off>>output.txt
    echo title Window>>output.txt
    echo attrib -h>>output.txt
    echo exit>>output.txt

    (Im Working on outputting folders) :)
    found this website on Google

  91. batch file output to text file? | Askjis Says:

    [...] isn’t adding carriage returns from word-wrapping or something similar. DutchUncle Says: – read more [...]

  92. Elmer B. Fuddled Says:

    For something that now seems so relatively easy, the headaches it has given me trying to find just this thing is unbelievable!!

    I use batch commands during unattended installs and up until now I’ve been guessing when I see on my screen “File not found” as to which it was.

    Many many THANKS!

    Bookmarked and noted your links for further reading.

    Elmer

  Theme Brought to you by Directory Journal and Elegant Directory.