Related
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?
To expand on davor's answer, you can use PowerShell like this:
powershell "dir | tee test.txt"
If you're trying to redirect the output of an exe in the current directory, you need to use .\ on the filename, eg:
powershell ".\something.exe | tee test.txt"
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.
There's a Win32 port of the Unix tee command, that does exactly that. See http://unxutils.sourceforge.net/ or http://getgnuwin32.sourceforge.net/
Check this out: wintee
No need for cygwin.
I did encounter and report some issues though.
Also you might check unxutils because it contains tee (and no need for cygwin), but beware that output EOL's are UNIX-like here.
Last, but not least, is if you have PowerShell, you could try Tee-Object. Type get-help tee-object in PowerShell console for more info.
#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.
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.
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.
This works, though it's a bit ugly:
dir >_ && type _ && type _ > a.txt
It's a little more flexible than some of the other solutions, in that it works statement-by-statement so you can use it to append as well. I use this quite a bit in batch files to log and display messages:
ECHO Print line to screen and log to file. >_ && type _ && type _ >> logfile.txt
Yes, you could just repeat the ECHO statement (once for the screen and the second time redirecting to the logfile), but that looks just as bad and is a bit of a maintenance issue. At least this way you don't have to make changes to messages in two places.
Note that _ is just a short filename, so you'll need to make sure to delete it at the end of your batch file (if you're using a batch file).
I’d like to expand a bit on Saxon Druce’s excellent answer.
As stated, you can redirect the output of an executable in the current directory like so:
powershell ".\something.exe | tee test.txt"
However, this only logs stdout to test.txt. It doesn’t also log stderr.
The obvious solution would be to use something like this:
powershell ".\something.exe 2>&1 | tee test.txt"
However, this won’t work for all something.exes. Some something.exes will interpret the 2>&1 as an argument and fail. The correct solution is to instead only have apostrophes around the something.exe and its switches and arguments, like so:
powershell ".\something.exe --switch1 --switch2 … arg1 arg2 …" 2^>^&1 ^| tee test.txt
Notice though, that in this case you have to escape the special cmd-shell characters ">&|" with a "^" each so they only get interpreted by powershell.
mtee is a small utility which works very well for this purpose. It's free, source is open, and it Just Works.
You can find it at http://www.commandline.co.uk.
Used in a batch file to display output AND create a log file simultaneously, the syntax looks like this:
someprocess | mtee /+ mylogfile.txt
Where /+ means to append output.
This assumes that you have copied mtee into a folder which is in the PATH, of course.
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.
If you have cygwin in your windows environment path you can use:
dir > a.txt | tail -f a.txt
dir 1>a.txt 2>&1 | type a.txt
This will help to redirect both STDOUT and STDERR
I know this is a very old topic, but in previous answers there is not a full implementation of a real time Tee written in Batch. My solution below is a Batch-JScript hybrid script that use the JScript section just to get the output from the piped command, but the processing of the data is done in the Batch section. This approach have the advantage that any Batch programmer may modify this program to fit specific needs. This program also correctly process the output of CLS command produced by other Batch files, that is, it clear the screen when CLS command output is detected.
#if (#CodeSection == #Batch) #then
#echo off
setlocal EnableDelayedExpansion
rem APATee.bat: Asynchronous (real time) Tee program, Batch-JScript hybrid version
rem Antonio Perez Ayala
rem The advantage of this program is that the data management is written in Batch code,
rem so any Batch programmer may modify it to fit their own needs.
rem As an example of this feature, CLS command is correctly managed
if "%~1" equ "" (
echo Duplicate the Stdout output of a command in the screen and a disk file
echo/
echo anyCommand ^| APATee teeFile.txt [/A]
echo/
echo If /A switch is given, anyCommand output is *appended* to teeFile.txt
goto :EOF
)
if "%2" equ ":TeeProcess" goto TeeProcess
rem Get the output of CLS command
for /F %%a in ('cls') do set "cls=%%a"
rem If /A switch is not provided, delete the file that receives Tee output
if /I "%~2" neq "/A" if exist %1 del %1
rem Create the semaphore-signal file and start the asynchronous Tee process
echo X > Flag.out
if exist Flag.in del Flag.in
Cscript //nologo //E:JScript "%~F0" | "%~F0" %1 :TeeProcess
del Flag.out
goto :EOF
:TeeProcess
rem Wait for "Data Available" signal
if not exist Flag.in goto TeeProcess
rem Read the line sent by JScript section
set line=
set /P line=
rem Set "Data Read" acknowledgement
ren Flag.in Flag.out
rem Check for the standard "End Of piped File" mark
if "!line!" equ ":_EOF_:" exit /B
rem Correctly manage CLS command
if "!line:~0,1!" equ "!cls!" (
cls
set "line=!line:~1!"
)
rem Duplicate the line in Stdout and the Tee output file
echo(!line!
echo(!line!>> %1
goto TeeProcess
#end
// JScript section
var fso = new ActiveXObject("Scripting.FileSystemObject");
// Process all lines of Stdin
while ( ! WScript.Stdin.AtEndOfStream ) {
// Read the next line from Stdin
var line = WScript.Stdin.ReadLine();
// Wait for "Data Read" acknowledgement
while ( ! fso.FileExists("Flag.out") ) {
WScript.Sleep(10);
}
// Send the line to Batch section
WScript.Stdout.WriteLine(line);
// Set "Data Available" signal
fso.MoveFile("Flag.out", "Flag.in");
}
// Wait for last "Data Read" acknowledgement
while ( ! fso.FileExists("Flag.out") ) {
WScript.Sleep(10);
}
// Send the standard "End Of piped File" mark
WScript.Stdout.WriteLine(":_EOF_:");
fso.MoveFile("Flag.out", "Flag.in");
I was also looking for the same solution, after a little try, I was successfully able to achieve that in Command Prompt. Here is my solution :
#Echo off
for /f "Delims=" %%a IN (xyz.bat) do (
%%a > _ && type _ && type _ >> log.txt
)
#Echo on
It even captures any PAUSE command as well.
Something like this should do what you need?
%DATE%_%TIME% > c:\a.txt & type c:\a.txt
ipconfig >> c:\a.txt & type c:\a.txt
ping localhost >> c:\a.txt & type c:\a.txt
pause
Here's a sample of what I've used based on one of the other answers
#echo off
REM SOME CODE
set __ERROR_LOG=c:\errors.txt
REM set __IPADDRESS=x.x.x.x
REM Test a variable
if not defined __IPADDRESS (
REM Call function with some data and terminate
call :TEE %DATE%,%TIME%,IP ADDRESS IS NOT DEFINED
goto :EOF
)
REM If test happens to be successful, TEE out a message and end script.
call :TEE Script Ended Successful
goto :EOF
REM THE TEE FUNCTION
:TEE
for /f "tokens=*" %%Z in ("%*") do (
> CON ECHO.%%Z
>> "%__ERROR_LOG%" ECHO.%%Z
goto :EOF
)
send output to console, append to console log, delete output from current command
dir >> usb-create.1 && type usb-create.1 >> usb-create.log | type usb-create.1 && del usb-create.1
This is a variation on a previous answer by MTS, however it adds some functionality that might be useful to others. Here is the method that I used:
A command is set as a variable, that can be used later throughout the code, to output to the command window and append to a log file, using set _Temp_Msg_Cmd=
the command has escaped redirection using the carrot ^ character so that the commands are not evaluated initially
A temporary file is created with a filename similar to the batch file being run called %~n0_temp.txt that uses command line parameter extension syntax %~n0 to get the name of the batch file.
The output is appended to a separate log file %~n0_log.txt
Here is the sequence of commands:
The output and error messages are sent to the temporary file ^> %~n0_temp.txt 2^>^&1
The content of the temporary file is then both:
appended to the logfile ^& type %~n0_temp.txt ^>^> %~n0_log.txt
output to the command window ^& type %~n0_temp.txt
The temporary file with the message is deleted ^& del /Q /F %~n0_temp.txt
Here is the example:
set _Temp_Msg_Cmd= ^> %~n0_temp.txt 2^>^&1 ^& type %~n0_temp.txt ^>^> %~n0_log.txt ^& type %~n0_temp.txt ^& del /Q /F %~n0_temp.txt
This way then the command can simply be appended after later commands in a batch file that looks a lot cleaner:
echo test message %_Temp_Msg_Cmd%
This can be added to the end of other commands as well. As far as I can tell it will work when messages have multiple lines. For example the following command outputs two lines if there is an error message:
net use M: /D /Y %_Temp_Msg_Cmd%
Just like unix.
dir | tee a.txt
Does work On windows XP, it requires mksnt installed.
It displays on the prompt as well as appends to the file.
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.
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.
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:
Incorrectly handles the \r character, output is mixed and messed (https://code.google.com/archive/p/wintee/issues/7 ).
Having other issues: https://code.google.com/archive/p/wintee/issues
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
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.
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
Does not support forward slash characters in the path to a log file (https://github.com/ritchielawrence/mtee/issues/6 )
Has a race condition issue, when can not extract a pipe process exit code because it has closed before it's access (https://github.com/ritchielawrence/mtee/issues/4 )
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.
#echo on
set startDate=%date%
set startTime=%time%
set /a sth=%startTime:~0,2%
set /a stm=1%startTime:~3,2% - 100
set /a sts=1%startTime:~6,2% - 100
fullprocess.bat > C:\LOGS\%startDate%_%sth%.%stm%.%sts%.LOG | fullprocess.bat
This will create a log file with the current datetime and you can the console lines during the process
I use a batch subroutine with a "for" statement to get the command output one line at a time and both write that line to a file and output it to the console.
#echo off
set logfile=test.log
call :ExecuteAndTee dir C:\Program Files
Exit /B 0
:ExecuteAndTee
setlocal enabledelayedexpansion
echo Executing '%*'
for /f "delims=" %%a in ('%* 2^>^&1') do (echo.%%a & echo.%%a>>%logfile%)
endlocal
Exit /B 0
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.
This works in real time but is also kind a ugly and the performance is slow. Not well tested either:
#echo off
cls
SET MYCOMMAND=dir /B
ECHO File called 'test.bat' > out.txt
for /f "usebackq delims=" %%I in (`%MYCOMMAND%`) do (
ECHO %%I
ECHO %%I >> out.txt
)
pause
An alternative is to tee stdout to stderr within your program:
in java:
System.setOut(new PrintStream(new TeeOutputStream(System.out, System.err)));
Then, in your dos batchfile: java program > log.txt
The stdout will go to the logfile and the stderr (same data) will show on the console.
I install perl on most of my machines so an answer using perl: tee.pl
my $file = shift || "tee.dat";
open $output, ">", $file or die "unable to open $file as output: $!";
while(<STDIN>)
{
print $_;
print $output $_;
}
close $output;
dir | perl tee.pl
or
dir | perl tee.pl dir.bat
crude and untested.
I made a Main batch file with the lines below:
#echo off
color 1e
title ------ Just a Test ------
start "C:\Users\%USERNAME%\Desktop\Check.bat"
:START
echo Welcome to the Game!
...
And Check.bat contains:
#echo off
if not exist "C:\Users\%USERNAME%\Desktop\Batch_System\importantFile.dll" goto ERROR
if exist "C:\Users\%USERNAME%\Desktop\Batch_System\importantFile.dll" goto CONTINUE
:ERROR
cls
echo ERROR :
echo Important file not found. please reinstall the program
pause
exit /b
:CONTINUE
cls
exit /b
When I use the command start, it starts only a command prompt with the Check.bat directory and the main batch file continues executing the game. I want to force close the main batch file if importantFile.dll doesn't exist.
Okay, let me explain: When the main batch file is executed and runs the command start to start another batch file called Check.bat, the file Check.bat checks if the file importantFile.dll exists, and if not, Check.bat displays an error message.
Does anyone know how to write Check.bat in a manner that when the .dll file does not exist, force the main batch file to exit?
First, help on every command can be get by running in a command prompt window the command with /? as parameter. start /? outputs the help of command START. call /? outputs the help of command CALL usually used to run a batch file from within a batch file. Those two commands can be used to run a batch file as explained in detail in answer on How to call a batch file that is one level up from the current directory?
Second, the command line
start "C:\Users\%USERNAME%\Desktop\Check.bat"
starts a new command process in foreground with a console window with full qualified batch file name as window title displayed in title bar at top of the console window. That is obviously not wanted by you.
Third, the Wikipedia article Windows Environment Variables lists the predefined environment variables on Windows and their default values depending on version of Windows.
In general it is better to use "%USERPROFILE%\Desktop" instead of "C:\Users\%USERNAME%\Desktop".
There is no C:\Users on Windows prior Windows Vista and Windows Server 2008 by default at all.
The users profile directory can be on a different drive than drive C:.
It is also possible that just the current user's profile directory is not in C:\Users, for example on a Windows server on which many users can logon directly and for which the server administrator decided to have the users' profile directories on a different drive than system drive making backup and cleaning operations on server much easier and is also better for security.
Well, it is also possible to have the user's desktop folder not in the user's profile directory. But that is really, really uncommon.
Fourth, on shipping a set of batch files, it is recommended to use %~dp0 to call other batch files from within a batch file because of this string referencing drive and path of argument 0 expands to full path of currently executed batch file.
The batch file path referenced with %~dp0 always ends with a backslash. Therefore concatenate %~dp0 always without an additional backslash with another batch file name, folder or file name.
See also What is the reason for batch file path referenced with %~dp0 sometimes changes on changing directory?
Fifth, I suggest following for your two batch files:
Main.bat:
#echo off
color 1e
title ------ Just a Test ------
call "%~dp0Check.bat" || color && exit /B
echo Welcome to the Game!
Check.bat:
#echo off
cls
if exist "%~dp0Batch_System\importantFile.dll" exit /B 0
echo ERROR:
echo Important file not found. Please reinstall the program.
echo/
pause
exit /B 1
The batch file Check.bat is exited explicitly on important file existing with returning exit code 0 to the parent batch file Main.bat. For that reason Windows command processor continues execution of Main.bat on the command line below the command line calling the batch file Check.bat.
Otherwise Check.bat outputs an error message, waits for a pressed key by the user and exits explicitly with non zero exit code 1. The non zero exit code results in Main.bat in executing the next command after || which is COLOR to restore initial colors and next executing also EXIT with option /B to exit the execution of Main.bat.
See also:
Single line with multiple commands using Windows batch file
What are the ERRORLEVEL values set by internal cmd.exe commands?
Which cmd.exe internal commands clear the ERRORLEVEL to 0 upon success?
Where does GOTO :EOF return to?
exit /B without an additionally specified exit code is like goto :EOF.
The CALL command line in Main.bat could be also written as:
call "%~dp0Check.bat" || ( color & exit /B )
And Main.bat could be also written as:
#echo off
color 1e
title ------ Just a Test ------
call "%~dp0Check.bat"
if errorlevel 1 (
color
goto :EOF
)
echo Welcome to the Game!
I do not recommend using in Main.bat just EXIT instead of exit /B or goto :EOF. Just EXIT would result in exiting the current command process independent on calling hierarchy and independent on how the command process was started: with option /K to keep it running to see error messages like on opening a command prompt window and next running a batch file from within command prompt window, or with /C to close the command process after application/command/script execution finished like on double clicking on a batch file.
It is advisable to test batch files by running them from within an opened command prompt window instead of double clicking on them to see error messages on syntax errors output by cmd.exe. For that reason usage of just EXIT is counter-productive for a batch file in development. Run cmd /? in a command prompt window for help on Windows command processor itself.
Last but not least see:
Microsoft's command-line reference
SS64.com - A-Z index of the Windows CMD command line
start is asynchronous by default. Use start /wait so that main.bat can test the exit code of check.bat. Make check.bat return an appropriate exit code.
For example...
main.bat
#echo off
start /b /wait check.bat
if not %errorlevel% == 0 exit /b
echo "Welcome to the game!"
...
check.bat
#echo off
if exist "importantfile.dll" exit 0
echo ERROR: Important file not found. Please reinstall the program.
pause
exit 1
notes
Added /b to start to avoid opening another window. Change that per your preference.
You could use call instead of start but call gives the called code access to the variables of main.bat so encapsulation is improved if you use start as you did.
The logic in check.bat is simplified above. Once you identify the success path early in the script and exit, the rest of the script can assume the fail path. This saves you a few if's and labels which you might find simplifies writing and reading of similar scripts. Beware of potentially confusing multiple exit points in longer scripts though!
When choosing exit codes, 0 is a common convention for success.
The above code is just one technique - there are several other options (such as checksomething && dosomethingifok). Some useful information on return codes, and checking them, can be found in http://steve-jansen.github.io/guides/windows-batch-scripting/part-3-return-codes.html
Thanks to the answer from Mofi. I've my example and exp. on this. To be short, it's about the setting of log date format. You may change the format of time , date and log. you may have the result.
why-batch-file-run-with-failure-in-windows-server
I've recently started working with .bat files, and I'm trying to redirect the output to a file.
I've found 2 options, so far:
echo aaa > out.txt - which sends the output of the single echo command to the specified file (can also be appended using >>)
calling the entire file from the cmd using somefile.bat > out.txt (which is actually similar to number 1, as it sends the output of the single command somefile.bat to out.txt)
What I'm looking for is something else - I'm trying to have a line in my file that sends all the output from that point forth to the file.
Thanks!
echo this goes to screen
(
echo this line goes to the file
echo also this line and the ping-output
ping www.stackoverflow.com
echo and this
)>file.txt
echo this goes to screen again
Note:
all inside the block (between ( and )) is parsed at once. If you use variables inside the block, you may need delayed expansion.
There is no universal solution. It depends of the batch file requirements.
For a lot of batch files, the answer from Stephan will work without problems, taking in consideration what he pointed: all the code is inside a block and any variable management inside it may require delayed expansion.
Other alternative is to move the code under a subroutine, calling it with the redirection
#echo off
call :mainProcess %* > outputFile
exit /b
:mainProcess
:: here the batch file begins
echo %1 %2 %3
How to run commands in a batch file which is inside another batch file......
I am trying to run commands in different console other than command prompt in a batch file but not able to do so.I am able to start the other console in batch file but not able to pass commands on to it.
My first interpretation of the question led me to believe that Sampath wanted one batch script that has two sets of commands. Calling it would run the 1st set of commands in the parent window, and a second window would open that would run the same script with thd 2nd set of commands.
"%~f0" will give the full path to the currently executing batch script. A simple command line argument serves as a switch to determine which code to run.
#echo off
if "%~1"==":PART2" goto %~1
::use this line if 2nd window is to remain open upon completion
::start "%~f0" :PART2
::use this line if 2nd window is to close upon completion
start cmd /c "%~f0" :PART2
echo Test parent output
pause
exit /b
:PART2
echo Test child output
pause
exit /b
Andriy M suggests Sampath wants to be able to dynamically send commands to the 2nd window. This can be done with 2 scripts that I will call master.bat and slave.bat.
The slave.bat simply reads commands from stdin and executes them. The master.bat launches the slave with input redirected to a command file and then appends commands to the command file.
Here is an example of master.bat that demonstrates dymamically sending commands to the slave. Note that the master prompts for a command, but the slave window will have the focus. Make sure you click on the master so you can enter the command of your choice.
#echo off
:: create an empty command file
type nul >cmds.txt
:: start the slave with input redirected to the command file
start slave.bat ^<cmds.txt
:: issue some commands by appending them to the command file
>>cmds.txt echo echo command 1
>>cmds.txt echo echo command 2
>>cmds.txt echo echo(
>>cmds.txt echo rem /?
:: ask for a command to send to the slave
set /p "cmd=Enter a command to be sent to the slave: "
:: send the command
>>cmds.txt echo %cmd%
::pause so we can see the results in the slave window
for /l %%n in (1 1 1000000) do rem
::tell the slave to exit
>>cmds.txt echo exit
And here is the slave.bat
#echo off
:top
set "cmd="
set /p "cmd="
%cmd%
goto :top
You could try a call statement:
call batchname.bat
this will run the specified batch file in the current open prompt
It almost sounds like what you want is a file that holds commands that you want to run, and to use a batch script to call on those commands when you want?
I've implemented this by creating a batch file that holds all the commands (code snippets) that I find useful, and then using my other batch scripts to call on that "master" file for my snippets.
For example, in my MASTER_BAT.BAT file, an example of a snippet to create dates in different format for usage look like this:
GOTO:%~1
:GET_CURRENT_DATE
:: Created: 1/19/2012
:: Creates variables for the date format in different forms.
:: No additional arguments required
SET DISABLED=0
IF [%DISABLED%] == [1] GOTO:EOF
:: Created: 11/30/11
:: Creates date formats.
Set mdy=%date:~4,2%-%date:~7,2%-%date:~12,4%
Set mdY=%date:~4,2%-%date:~7,2%-%date:~10,4%
Set Dmdy=%date:~0,4%%date:~4,2%-%date:~7,2%-%date:~12,4%
Set DmdY=%date:~0,4%%date:~4,2%-%date:~7,2%-%date:~10,4%
Set ymd=%date:~12,4%-%date:~4,2%-%date:~7,2%
Set ymd=%date:~10,4%-%date:~4,2%-%date:~7,2%
GOTO:EOF
And in my CHILD_BAT.BAT, I want to use that snippet to create the date formats... lets say I want to make it so that I can call the date by the current date in mm/dd/yy format:
CALL MASTER_BAT.BAT "GET_CURRENT_DATE"
ECHO %mdy%
PAUSE
Your output for CHILD_BAT.BAT would be:
1-23-12
Press any key to continue...
Also, any variables created in your CHILD_BAT.BAT prior to the CALL command will be passed to the MASTER_BAT.BAT script as well. However, for loop interation that includes a CALL will not pass the for loop temporary variable.
Hope this is helpful.
EDIT: Note that my snippet is usable for the U.S. date format.
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?
To expand on davor's answer, you can use PowerShell like this:
powershell "dir | tee test.txt"
If you're trying to redirect the output of an exe in the current directory, you need to use .\ on the filename, eg:
powershell ".\something.exe | tee test.txt"
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.
There's a Win32 port of the Unix tee command, that does exactly that. See http://unxutils.sourceforge.net/ or http://getgnuwin32.sourceforge.net/
Check this out: wintee
No need for cygwin.
I did encounter and report some issues though.
Also you might check unxutils because it contains tee (and no need for cygwin), but beware that output EOL's are UNIX-like here.
Last, but not least, is if you have PowerShell, you could try Tee-Object. Type get-help tee-object in PowerShell console for more info.
#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.
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.
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.
This works, though it's a bit ugly:
dir >_ && type _ && type _ > a.txt
It's a little more flexible than some of the other solutions, in that it works statement-by-statement so you can use it to append as well. I use this quite a bit in batch files to log and display messages:
ECHO Print line to screen and log to file. >_ && type _ && type _ >> logfile.txt
Yes, you could just repeat the ECHO statement (once for the screen and the second time redirecting to the logfile), but that looks just as bad and is a bit of a maintenance issue. At least this way you don't have to make changes to messages in two places.
Note that _ is just a short filename, so you'll need to make sure to delete it at the end of your batch file (if you're using a batch file).
I’d like to expand a bit on Saxon Druce’s excellent answer.
As stated, you can redirect the output of an executable in the current directory like so:
powershell ".\something.exe | tee test.txt"
However, this only logs stdout to test.txt. It doesn’t also log stderr.
The obvious solution would be to use something like this:
powershell ".\something.exe 2>&1 | tee test.txt"
However, this won’t work for all something.exes. Some something.exes will interpret the 2>&1 as an argument and fail. The correct solution is to instead only have apostrophes around the something.exe and its switches and arguments, like so:
powershell ".\something.exe --switch1 --switch2 … arg1 arg2 …" 2^>^&1 ^| tee test.txt
Notice though, that in this case you have to escape the special cmd-shell characters ">&|" with a "^" each so they only get interpreted by powershell.
mtee is a small utility which works very well for this purpose. It's free, source is open, and it Just Works.
You can find it at http://www.commandline.co.uk.
Used in a batch file to display output AND create a log file simultaneously, the syntax looks like this:
someprocess | mtee /+ mylogfile.txt
Where /+ means to append output.
This assumes that you have copied mtee into a folder which is in the PATH, of course.
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.
If you have cygwin in your windows environment path you can use:
dir > a.txt | tail -f a.txt
dir 1>a.txt 2>&1 | type a.txt
This will help to redirect both STDOUT and STDERR
I know this is a very old topic, but in previous answers there is not a full implementation of a real time Tee written in Batch. My solution below is a Batch-JScript hybrid script that use the JScript section just to get the output from the piped command, but the processing of the data is done in the Batch section. This approach have the advantage that any Batch programmer may modify this program to fit specific needs. This program also correctly process the output of CLS command produced by other Batch files, that is, it clear the screen when CLS command output is detected.
#if (#CodeSection == #Batch) #then
#echo off
setlocal EnableDelayedExpansion
rem APATee.bat: Asynchronous (real time) Tee program, Batch-JScript hybrid version
rem Antonio Perez Ayala
rem The advantage of this program is that the data management is written in Batch code,
rem so any Batch programmer may modify it to fit their own needs.
rem As an example of this feature, CLS command is correctly managed
if "%~1" equ "" (
echo Duplicate the Stdout output of a command in the screen and a disk file
echo/
echo anyCommand ^| APATee teeFile.txt [/A]
echo/
echo If /A switch is given, anyCommand output is *appended* to teeFile.txt
goto :EOF
)
if "%2" equ ":TeeProcess" goto TeeProcess
rem Get the output of CLS command
for /F %%a in ('cls') do set "cls=%%a"
rem If /A switch is not provided, delete the file that receives Tee output
if /I "%~2" neq "/A" if exist %1 del %1
rem Create the semaphore-signal file and start the asynchronous Tee process
echo X > Flag.out
if exist Flag.in del Flag.in
Cscript //nologo //E:JScript "%~F0" | "%~F0" %1 :TeeProcess
del Flag.out
goto :EOF
:TeeProcess
rem Wait for "Data Available" signal
if not exist Flag.in goto TeeProcess
rem Read the line sent by JScript section
set line=
set /P line=
rem Set "Data Read" acknowledgement
ren Flag.in Flag.out
rem Check for the standard "End Of piped File" mark
if "!line!" equ ":_EOF_:" exit /B
rem Correctly manage CLS command
if "!line:~0,1!" equ "!cls!" (
cls
set "line=!line:~1!"
)
rem Duplicate the line in Stdout and the Tee output file
echo(!line!
echo(!line!>> %1
goto TeeProcess
#end
// JScript section
var fso = new ActiveXObject("Scripting.FileSystemObject");
// Process all lines of Stdin
while ( ! WScript.Stdin.AtEndOfStream ) {
// Read the next line from Stdin
var line = WScript.Stdin.ReadLine();
// Wait for "Data Read" acknowledgement
while ( ! fso.FileExists("Flag.out") ) {
WScript.Sleep(10);
}
// Send the line to Batch section
WScript.Stdout.WriteLine(line);
// Set "Data Available" signal
fso.MoveFile("Flag.out", "Flag.in");
}
// Wait for last "Data Read" acknowledgement
while ( ! fso.FileExists("Flag.out") ) {
WScript.Sleep(10);
}
// Send the standard "End Of piped File" mark
WScript.Stdout.WriteLine(":_EOF_:");
fso.MoveFile("Flag.out", "Flag.in");
I was also looking for the same solution, after a little try, I was successfully able to achieve that in Command Prompt. Here is my solution :
#Echo off
for /f "Delims=" %%a IN (xyz.bat) do (
%%a > _ && type _ && type _ >> log.txt
)
#Echo on
It even captures any PAUSE command as well.
Something like this should do what you need?
%DATE%_%TIME% > c:\a.txt & type c:\a.txt
ipconfig >> c:\a.txt & type c:\a.txt
ping localhost >> c:\a.txt & type c:\a.txt
pause
Here's a sample of what I've used based on one of the other answers
#echo off
REM SOME CODE
set __ERROR_LOG=c:\errors.txt
REM set __IPADDRESS=x.x.x.x
REM Test a variable
if not defined __IPADDRESS (
REM Call function with some data and terminate
call :TEE %DATE%,%TIME%,IP ADDRESS IS NOT DEFINED
goto :EOF
)
REM If test happens to be successful, TEE out a message and end script.
call :TEE Script Ended Successful
goto :EOF
REM THE TEE FUNCTION
:TEE
for /f "tokens=*" %%Z in ("%*") do (
> CON ECHO.%%Z
>> "%__ERROR_LOG%" ECHO.%%Z
goto :EOF
)
send output to console, append to console log, delete output from current command
dir >> usb-create.1 && type usb-create.1 >> usb-create.log | type usb-create.1 && del usb-create.1
This is a variation on a previous answer by MTS, however it adds some functionality that might be useful to others. Here is the method that I used:
A command is set as a variable, that can be used later throughout the code, to output to the command window and append to a log file, using set _Temp_Msg_Cmd=
the command has escaped redirection using the carrot ^ character so that the commands are not evaluated initially
A temporary file is created with a filename similar to the batch file being run called %~n0_temp.txt that uses command line parameter extension syntax %~n0 to get the name of the batch file.
The output is appended to a separate log file %~n0_log.txt
Here is the sequence of commands:
The output and error messages are sent to the temporary file ^> %~n0_temp.txt 2^>^&1
The content of the temporary file is then both:
appended to the logfile ^& type %~n0_temp.txt ^>^> %~n0_log.txt
output to the command window ^& type %~n0_temp.txt
The temporary file with the message is deleted ^& del /Q /F %~n0_temp.txt
Here is the example:
set _Temp_Msg_Cmd= ^> %~n0_temp.txt 2^>^&1 ^& type %~n0_temp.txt ^>^> %~n0_log.txt ^& type %~n0_temp.txt ^& del /Q /F %~n0_temp.txt
This way then the command can simply be appended after later commands in a batch file that looks a lot cleaner:
echo test message %_Temp_Msg_Cmd%
This can be added to the end of other commands as well. As far as I can tell it will work when messages have multiple lines. For example the following command outputs two lines if there is an error message:
net use M: /D /Y %_Temp_Msg_Cmd%
Just like unix.
dir | tee a.txt
Does work On windows XP, it requires mksnt installed.
It displays on the prompt as well as appends to the file.
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.
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.
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:
Incorrectly handles the \r character, output is mixed and messed (https://code.google.com/archive/p/wintee/issues/7 ).
Having other issues: https://code.google.com/archive/p/wintee/issues
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
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.
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
Does not support forward slash characters in the path to a log file (https://github.com/ritchielawrence/mtee/issues/6 )
Has a race condition issue, when can not extract a pipe process exit code because it has closed before it's access (https://github.com/ritchielawrence/mtee/issues/4 )
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.
#echo on
set startDate=%date%
set startTime=%time%
set /a sth=%startTime:~0,2%
set /a stm=1%startTime:~3,2% - 100
set /a sts=1%startTime:~6,2% - 100
fullprocess.bat > C:\LOGS\%startDate%_%sth%.%stm%.%sts%.LOG | fullprocess.bat
This will create a log file with the current datetime and you can the console lines during the process
I use a batch subroutine with a "for" statement to get the command output one line at a time and both write that line to a file and output it to the console.
#echo off
set logfile=test.log
call :ExecuteAndTee dir C:\Program Files
Exit /B 0
:ExecuteAndTee
setlocal enabledelayedexpansion
echo Executing '%*'
for /f "delims=" %%a in ('%* 2^>^&1') do (echo.%%a & echo.%%a>>%logfile%)
endlocal
Exit /B 0
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.
This works in real time but is also kind a ugly and the performance is slow. Not well tested either:
#echo off
cls
SET MYCOMMAND=dir /B
ECHO File called 'test.bat' > out.txt
for /f "usebackq delims=" %%I in (`%MYCOMMAND%`) do (
ECHO %%I
ECHO %%I >> out.txt
)
pause
An alternative is to tee stdout to stderr within your program:
in java:
System.setOut(new PrintStream(new TeeOutputStream(System.out, System.err)));
Then, in your dos batchfile: java program > log.txt
The stdout will go to the logfile and the stderr (same data) will show on the console.
I install perl on most of my machines so an answer using perl: tee.pl
my $file = shift || "tee.dat";
open $output, ">", $file or die "unable to open $file as output: $!";
while(<STDIN>)
{
print $_;
print $output $_;
}
close $output;
dir | perl tee.pl
or
dir | perl tee.pl dir.bat
crude and untested.