显示Windows命令提示符输出并将其redirect到文件

如何在Windows命令提示符下运行命令行应用程序,并使输出同时显示并redirect到文件?

例如,如果我要运行命令dir > test.txt ,则会将输出redirect到名为test.txt的文件,而不显示结果。

我怎么能写一个命令来显示输出redirect输出到Windows命令提示符下的文件,类似于Unix上的tee命令?

我能够find一个解决scheme/解决方法redirect输出到一个文件,然后到控制台:

 dir > a.txt | type a.txt 

其中dir是输出需要redirect的命令, a.txt是存储输出的文件。

Unix tee命令有一个Win32端口,就是这样做的。 请参阅http://unxutils.sourceforge.net/或http://getgnuwin32.sourceforge.net/

为了扩展davor的答案 ,你可以像这样使用PowerShell:

 powershell "dir | tee test.txt" 

如果你试图在当前目录中redirectexe的输出,你需要在文件名上使用.\ ,例如:

 powershell ".\something.exe | tee test.txt" 

看看这个: wintee

不需要cygwin。

尽pipe我遇到并报告了一些问题。

你也可以检查unxutils,因为它包含tee(并且不需要cygwin),但是要注意输出的EOL是类UNIX的。

最后但并非最不重要的是,如果你有PowerShell,你可以尝试Tee-Object。 在PowerShell控制台中键入get-help tee-object以获取更多信息。

@ tori3852

我find

 dir > a.txt | type a.txt 

没有工作(前几行dir列表只有 – 怀疑某种过程分叉和第二部分,'types'命令在可怕的上市完成之前终止?),所以相反,我用:

 dir > z.txt && type z.txt 

其中 – 顺序命令,一个在第二个开始之前完成。

谢谢。
很高兴find这个东西,感激。

一个简单的C#控制台应用程序可以做到这一点:

 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()); } } } 

要使用它,只需将source命令input到程序中,并提供要复制输出的任何文件的path。 例如:

 dir | CopyToFiles files1.txt files2.txt 

将显示目录的结果,并将结果保存在files1.txt和files2.txt中。

请注意,在上面的error handling方式中没有太多(任何东西!),支持多个文件可能实际上并不需要。

不幸的是没有这样的事情。

Windows控制台应用程序只有一个输出句柄。 (好吧,有两个STDOUTSTDERR但是这里没关系) >将通常写入控制台句柄的输出redirect到一个文件句柄。

如果您想要进行某种多路复用,则必须使用可以将输出转移到的外部应用程序。 这个应用程序然后可以再次写入文件和控制台。

虽然这有点难看,

 dir >_ && type _ && type _ > a.txt 

它比其他一些解决scheme更灵活一些,因为它可以逐个声明地工作,所以你也可以使用它来追加。 我在batch file中使用了相当多的东西来logging和显示消息:

 ECHO Print line to screen and log to file. >_ && type _ && type _ >> logfile.txt 

是的,您可以重复ECHO语句(一次用于屏幕,第二次redirect到日志文件),但看起来同样糟糕,有点维护问题。 至less这样你不必在两个地方修改邮件。

请注意,_只是一个简短的文件名,因此您需要确保在batch file末尾(如果使用的是batch file)将其删除。

mtee是一个非常适合这个目的的小公共事业。 它是免费的,源代码是开放的,它只是工作。

你可以在http://www.commandline.co.ukfind它。;

用于batch file中显示输出并同时创build一个日志文件,语法如下所示:

  someprocess | mtee /+ mylogfile.txt 

其中/ +表示追加输出。

这假定您已经将mtee复制到PATH中的文件夹中,当然。

我同意Brian Rasmussen的观点,unxutils port是最简单的方法。 在他的脚本页面的batch file部分Rob van der Woude提供了有关使用MS-DOS和CMD命令的大量信息。 我以为他可能有一个本地解决你的问题,并在那里挖后,我发现TEE.BAT ,这似乎是一个MS-DOS的三通的批处理语言实现。 这是一个相当复杂的batch file,我的倾向仍然是使用unxutils端口。

我想就撒克逊德鲁士的出色答案做一点点扩充。

如上所述,你可以像下面这样在当前目录中redirect一个可执行文件的输出:

 powershell ".\something.exe | tee test.txt" 

但是,这只会loggingtest.txt stdout 。 它不loggingstderr

显而易见的解决scheme是使用这样的东西:

 powershell ".\something.exe 2>&1 | tee test.txt" 

但是,这不适用于所有的something.exe 。 某些something.exe会将2>&1作为参数解释并失败。 正确的解决scheme是,而不是只有在something.exe周围的撇号,它是开关和参数,如下所示:

 powershell ".\something.exe --switch1 --switch2 … arg1 arg2 …" 2>&1 | tee test.txt 

dir 1>a.txt 2>&1 | type a.txt

这将有助于redirectSTDOUT和STDERR

如果你的Windows环境path中有cygwin,你可以使用:

  dir > a.txt | tail -f a.txt 

我也在寻找相同的解决scheme,经过一番尝试,我成功地在命令提示符下实现了这一点。 这是我的解决scheme:

 @Echo off for /f "Delims=" %%a IN (xyz.bat) do ( %%a > _ && type _ && type _ >> log.txt ) @Echo on 

它甚至捕获任何PAUSE命令。

以下是我根据其他答案之一所使用的示例

 @echo off REM SOME CODE set __ERROR_LOG=c:\errors.txt REM set __IPADDRESS=xxxx 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 ) 
 @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 

这将创build一个包含当前date时间的日志文件,您可以在过程中使用控制台行

我知道这是一个非常古老的话题,但是在之前的答案中并没有充分实现用Batch编写的实时Tee。 我下面的解决scheme是一个Batch-JScript混合脚本,它使用JScript部分来获取pipe道命令的输出,但是数据的处理是在Batch部分完成的。 这种方法的优点是,任何批处理程序员可以修改这个程序,以适应特定的需求。 该程序还能正确处理其他batch file产生的CLS命令输出,即检测到CLS命令输出时清除屏幕。

 @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"); 

像这样的东西应该做你需要的东西?

 %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 

发送输出到控制台,追加到控制台日志,删除当前命令的输出

 dir >> usb-create.1 && type usb-create.1 >> usb-create.log | type usb-create.1 && del usb-create.1 

如果你想在屏幕上看到真正的东西,即使batch file被redirect到一个文件,以下的帮助。 如果redirect到文件,设备CON也可以使用

例:

 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 

另请参阅好的redirect说明: http : //www.p-dd.com/chapter7-page14.html

如何显示和redirect输出到文件。 假设我使用dos命令,dir> test.txt,这个命令会将输出redirect到文件test.txt而不显示结果。 如何编写一个命令来显示输出并将输出redirect到使用DOS的文件,即Windows命令提示符,而不是在UNIX / LINUX中。

您可能会发现这些命令在biterscripting( http://www.biterscripting.com )有用。

 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. 

这实时工作,但也是一个丑陋的,performance是缓慢的。 没有很好地testing:

 @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 

另一种方法是在您的程序中将stdout标记为stderr:

在java中:

 System.setOut(new PrintStream(new TeeOutputStream(System.out, System.err))); 

然后,在你的dosbatch file中: java program > log.txt

标准输出将转到日志文件,stderr(相同的数据)将显示在控制台上。

就像unix一样

dir | tee a.txt

在Windows XP上,它需要安装mksnt

它显示在promt上并附加到文件中

我在我的大多数机器上安装perl,所以使用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或dir | perl tee.pl dir.bat

原油和未经testing。

这是MTS以前的答案的一个变种,但它增加了一些可能对其他人有用的function。 这是我使用的方法:

  • 一个命令被设置为一个variables,可以在整个代码中使用,输出到命令窗口set _Temp_Msg_Cmd=加到一个日志文件,使用set _Temp_Msg_Cmd=
    • 该命令已经使用胡萝卜^字符转义redirect ,以便命令不被初始化
  • 创build一个临时文件,其文件名与正在运行的batch file%~n0_temp.txt ,使用命令行参数扩展语法 %~n0 %~n0_temp.txt来获取batch file的名称。
  • 输出附加到单独的日志文件%~n0_log.txt

这里是命令的顺序:

  1. 输出和错误消息被发送到临时文件^> %~n0_temp.txt 2^>^&1
  2. 临时文件的内容是:
    • 追加到日志文件^& type %~n0_temp.txt ^>^> %~n0_log.txt
    • 输出到命令窗口^& type %~n0_temp.txt
  3. 带有消息的临时文件被删除^& del /Q /F %~n0_temp.txt

这是一个例子:

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

通过这种方式,命令可以简单地追加到后面的命令后面的batch file中:

echo test message %_Temp_Msg_Cmd%

这也可以添加到其他命令的末尾。 据我可以告诉它将工作时消息有多行。 例如,如果出现错误消息,则以下命令输出两行:

net use M: /D /Y %_Temp_Msg_Cmd%

我使用带“for”语句的批处理子程序一次获取一行命令,并将该行写入文件并将其输出到控制台。

 @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