Displaying Windows command prompt output and redirecting it to a file

Viewed 570283

How can I run a command-line application in the Windows command prompt and have the output both displayed and redirected to a file at the same time?

If, for example, I were to run the command dir > test.txt, this would redirect output to a file called test.txt without displaying the results.

How could I write a command to display the output and redirect output to a file in the Windows command prompt, similar to the tee command on Unix?

32 Answers

I was able to find a solution/workaround of redirecting output to a file and then to the console:

dir > a.txt | type a.txt

where dir is the command which output needs to be redirected, a.txt a file where to store output.

@tori3852

I found that

dir > a.txt | type a.txt

didn't work (first few lines of dir listing only - suspect some sort of process forking and the second part, the 'type' command terminated before the dire listing had completed? ), so instead I used:

dir > z.txt && type z.txt

which did - sequential commands, one completes before the second starts.

Unfortunately there is no such thing.

Windows console applications only have a single output handle. (Well, there are two STDOUT, STDERR but it doesn't matter here) The > redirects the output normally written to the console handle to a file handle.

If you want to have some kind of multiplexing you have to use an external application which you can divert the output to. This application then can write to a file and to the console again.

A simple C# console application would do the trick:

using System;
using System.Collections.Generic;
using System.IO;

namespace CopyToFiles
{
    class Program
    {
        static void Main(string[] args)
        {
            var buffer = new char[100];
            var outputs = new List<TextWriter>();

            foreach (var file in args)
                outputs.Add(new StreamWriter(file));

            outputs.Add(Console.Out);

            int bytesRead;
            do
            {
                bytesRead = Console.In.ReadBlock(buffer, 0, buffer.Length);
                outputs.ForEach(o => o.Write(buffer, 0, bytesRead));
            } while (bytesRead == buffer.Length);

            outputs.ForEach(o => o.Close());
        }
    }
}

To use this you just pipe the source command into the program and provide the path of any files you want to duplicate the output to. For example:

dir | CopyToFiles files1.txt files2.txt 

Will display the results of dir as well as store the results in both files1.txt and files2.txt.

Note that there isn't much (anything!) in the way of error handling above, and supporting multiple files may not actually be required.

I agree with Brian Rasmussen, the unxutils port is the easiest way to do this. In the Batch Files section of his Scripting Pages Rob van der Woude provides a wealth of information on the use MS-DOS and CMD commands. I thought he might have a native solution to your problem and after digging around there I found TEE.BAT, which appears to be just that, an MS-DOS batch language implementation of tee. It is a pretty complex-looking batch file and my inclination would still be to use the unxutils port.

This is not another answer, but more an overview and clarification to the already existed answers like Displaying Windows command prompt output and redirecting it to a file and others

I've found for myself that there is a set of issues what makes a set of tee implementations are not reliable in the Windows (Windows 7 in mine case).

I need to use specifically a tee implementation because have already uses a batch script with self redirection:

@echo off

setlocal


... some conditions here ..

rem the redirection
"%COMSPEC%" /C call %0 %* 2>&1 | "<path_to_tee_utililty>" ".log\<log_file_name_with_date_and_time>.%~nx0.log"
exit /b

:IMPL
... here the rest of script ...

The script and calls to some utilities inside the script can break the output if used together with a tee utility.


  1. The gnuwin32 implementation:

http://gnuwin32.sourceforge.net/packages/coreutils.htm

Pros:

  • Correctly handles standard output together with a console progress bar, where the \r character is heavily used.

Cons:

  • Makes console progress bars to draw only in a log file, but it has not duplicated or visible in the console window.
  • Throws multiple error messages Cwrite error: No such file or directory because seems the cmd interpreter closes the pipe/stdout too early and can not self close after that (spamming until termination).
  • Does not duplicate/print the output from the pause command (Press any key to continue...) in the console window.

  1. The wintee implementation:

https://code.google.com/archive/p/wintee/

https://github.com/rbuhl/wintee

Pros:

  • Shows a console progress bar both in the console window and in a log file (multiple prints).
  • Does duplicate/print the output from the pause command (Press any key to continue...) in the console window.

Cons:


  1. The UnxUtils implementation:

http://unxutils.sourceforge.net/

https://sourceforge.net/projects/unxutils/files/unxutils/current/

Pros

  • Shows a console progress bar both in the console window and in a log file (multiple prints).
  • Correctly handles the \r character.
  • Does duplicate/print the output from the pause command (Press any key to continue...) in the console window.

Cons

Not yet found


  1. The ss64.net implementation:

http://ss64.net/westlake/nt

http://ss64.net/westlake/nt/tee.zip

Pros:

  • Shows a console progress bar both in the console window and in a log file (multiple prints).

Cons:

  • Incorrectly handles the \r character, output is mixed and messed
  • For some reason does duplicate/print the output from the pause command (Press any key to continue...) in the console window AFTER a key press.

  1. The ritchielawrence mtee implementation:

https://ritchielawrence.github.io/mtee

https://github.com/ritchielawrence/mtee

Pros

  • Shows a console progress bar both in the console window and in a log file (multiple prints).
  • Correctly handles the \r character.
  • Does duplicate/print the output from the pause command (Press any key to continue...) in the console window.
  • The error code retain feature w/o a need to use workaround with the doskey (/E flag, Windows command interpreter: how to obtain exit code of first piped command )

Cons


So, if you are choosing the tee utility implementation between the above, then a better choice is the UnxUtils or mtee.


If you are searching for a better implementation with more features and less issues, then you can use callf utility:
https://github.com/andry81/contools/blob/trunk/Utilities/src/callf/help.tpl

You can run instead of:

call test.bat | mtee /E 1.log

This:

callf.exe /ret-child-exit /tee-stdout 1.log /tee-stdout-dup 1 "" "cmd.exe /c call test.bat"

It is better because it can pipe stdout separately from stderr and you can even pipe between processes with Administrator privileges isolation using named pipes.

If you're on the CLI, why not use a FOR loop to "DO" whatever you want:

for /F "delims=" %a in ('dir') do @echo %a && echo %a >> output.txt

Great resource on Windows CMD for loops: https://ss64.com/nt/for_cmd.html The key here is setting the delimeters (delims), that would break up each line of output, to nothing. This way it won't break on the default of white-space. The %a is an arbitrary letter, but it is used in the "do" section to, well... do something with the characters that were parsed at each line. In this case we can use the ampersands (&&) to execute the 2nd echo command to create-or-append (>>) to a file of our choosing. Safer to keep this order of DO commands in case there's an issue writing the file, we'll at least get the echo to the console first. The at sign (@) in front of the first echo suppresses the console from showing the echo-command itself, and instead just displays the result of the command which is to display the characters in %a. Otherwise you'd see:

echo Volume in drive [x] is Windows
Volume in drive [x] is Windows

UPDATE: /F skips blank lines and only fix is to pre-filter the output adding a character to every line (maybe with line-numbers via the command find). Solving this in CLI isn't quick or pretty. Also, I didn't include STDERR, so here's capturing errors as well:

for /F "delims=" %a in ('dir 2^>^&1') do @echo %a & echo %a >> output.txt

Redirecting Error Messages

The carets (^) are there to escape the symbols after them, because the command is a string that's being interpreted, as opposed to say, entering it directly on the command-line.

I just found a way to use the perl as alternative, e.g.:

CMD1 | perl -ne "print $_; print STDERR $_;" 2> OUTPUT.TEE

Following helps if you want something really seen on the screen - even if the batch file was redirected to a file. The device CON maybe used also if redirected to a file

Example:

ECHO first line on normal stdout. maybe redirected
ECHO second line on normal stdout again. maybe redirected
ECHO third line is to ask the user. not redirected  >CON
ECHO fourth line on normal stdout again. maybe redirected

Also see good redirection description: http://www.p-dd.com/chapter7-page14.html

How do I display and redirect output to a file. Suppose if I use dos command, dir > test.txt ,this command will redirect output to file test.txt without displaying the results. how to write a command to display the output and redirect output to a file using DOS i.e., windows command prompt, not in UNIX/LINUX.

You may find these commands in biterscripting ( http://www.biterscripting.com ) useful.

var str output
lf > $output
echo $output                            # Will show output on screen.
echo $output > "test.txt"               # Will write output to file test.txt.
system start "test.txt"                 # Will open file test.txt for viewing/editing.

Another variation is to split the pipe, and then re-direct the output as you like.

    @echo off
    for /f "tokens=1,* delims=:" %%P in ('findstr /n "^"') do (
      echo(%%Q
      echo(%%Q>&3
    )
    @exit/b %errorlevel%

Save the above to a .bat file. It splits text output on filestream 1 to filestream 3 also, which you can redirect as needed. In my examples below, I called the above script splitPipe.bat ...

    dir | splitPipe.bat  1>con  2>&1  3>my_stdout.log

    splitPipe.bat 2>nul < somefile.txt
  1. https://cygwin.com/install
  2. Click the link for "setup-x86_.exe"
  3. Run the installer
  4. On ~2nd page, choose a "mirror" to download from (I looked for a .edu domain)
  5. I said ok to the standard options
  6. Cygwin quickly finished install
  7. Open cmd
  8. Type c:\cygwin64\bin\script.exe and enter
  9. Type cmd and enter
  10. Run your program
  11. Type exit and enter (exits Cygwin's cmd.exe)
  12. Type exit and enter (exits Cygwin's script.exe)
  13. See the screen output of your program in text file called "typescript"
Related