如何在Windows命令提示符下运行命令行应用程序,并同时显示输出和重定向到文件?
例如,如果我要运行命令dir > test.txt
,这会将输出重定向到一个名为的文件,test.txt
而不显示结果。
我怎么能写一个命令来显示输出,并在Windows命令输出重定向到文件的提示,类似tee
的Unix命令?
如何在Windows命令提示符下运行命令行应用程序,并同时显示输出和重定向到文件?
例如,如果我要运行命令dir > test.txt
,这会将输出重定向到一个名为的文件,test.txt
而不显示结果。
我怎么能写一个命令来显示输出,并在Windows命令输出重定向到文件的提示,类似tee
的Unix命令?
Answers:
要扩展davor的答案,您可以使用PowerShell,如下所示:
powershell "dir | tee test.txt"
如果要重定向当前目录中exe的输出,则需要.\
在文件名上使用,例如:
powershell ".\something.exe | tee test.txt"
dir
在powershell中是一个别名,Get-ChildItem
与cmd的内部dir
命令不同。如果需要powershell "cmd /c dir | tee test.txt"
cmd内部版本,则需要
2>&1
,例如node 2>&1 | tee debug_log.txt
我能够找到将输出重定向到文件然后重定向到控制台的解决方案/解决方法:
dir > a.txt | type a.txt
其中dir是需要重定向输出的命令,a.txt是存储输出的文件。
&
而不是|
需要用于一些命令的输出,类似ping
或7z.exe
dir
。范例:chkdsk /f c: > c:\Temp.txt | c:\Temp.txt
。系统报告文件被另一个进程锁定。
handle output to stderr
-添加2>&1
重定向,如下所示:dir 2>&1 > a.txt & type a.txt
并且您应该将stderr与stdout混合在一起。
Unix tee
命令有一个Win32端口,可以做到这一点。请参阅http://unxutils.sourceforge.net/或http://getgnuwin32.sourceforge.net/
tee
包,你会发现在它gnuwin32.sourceforge.net/packages/coreutils.htm。
检查一下:wintee
不需要cygwin。
我确实遇到并报告了一些问题。
另外,您可能会检查unxutils,因为它包含tee(不需要cygwin),但是请注意,此处输出的EOL与UNIX类似。
最后但并非最不重要的一点是,如果您具有PowerShell,则可以尝试使用Tee-Object。get-help tee-object
在PowerShell控制台中键入以获取更多信息。
tee
实时输出。wtee
具有相同的功能。如果您不介意这些错误,那将会很好。
@ tori3852
我找到
dir > a.txt | type a.txt
不起作用(仅目录列表的前几行-怀疑某种过程分叉,而第二部分,“类型”命令在可怕列表完成之前终止了?),所以我改用:
dir > z.txt && type z.txt
这样做-顺序命令,一个在第二个开始之前完成。
&
代替。当命令中存在某种形式的错误并且您仍然希望在控制台上查看日志文件时,这很有用。请参阅Microsoft对此的文章。但是,这具有被设置为错误级别(将为0)的问题。&&
type
dir
%errorlevel%
type
一个简单的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());
}
}
}
要使用此功能,只需将源命令通过管道传递到程序中,并提供要将输出复制到的所有文件的路径。例如:
dir | CopyToFiles files1.txt files2.txt
将显示dir的结果,并将结果存储在files1.txt和files2.txt中。
请注意,上面的错误处理方式并没有太多(任何事情!),实际上可能不需要支持多个文件。
这很有效,尽管有点难看:
dir >_ && type _ && type _ > a.txt
它比其他一些解决方案灵活一些,因为它可以按语句运行,因此您也可以使用它来追加。我在批处理文件中经常使用此日志来记录和显示消息:
ECHO Print line to screen and log to file. >_ && type _ && type _ >> logfile.txt
是的,您可以重复ECHO语句(一次在屏幕上,第二次重定向到日志文件),但这看起来同样糟糕,并且有点维护问题。至少通过这种方式,您不必在两个地方都对消息进行更改。
请注意,_只是一个短文件名,因此您需要确保在批处理文件的末尾将其删除(如果使用的是批处理文件)。
type
命令放在单独的行中(在子例程中)可以解决该问题。
mtee是一个小型工具,可以很好地实现此目的。它是免费的,源是开放的,并且可以正常工作。
您可以在http://www.commandline.co.uk上找到它 。
用于批处理文件以显示输出并同时创建日志文件,语法如下所示:
someprocess | mtee /+ mylogfile.txt
/ +表示附加输出。
假定您已经将mtee复制到了PATH中的文件夹中。
我想对撒克逊·德鲁斯的出色回答做些补充。
如前所述,您可以像这样在当前目录中重定向可执行文件的输出:
powershell ".\something.exe | tee test.txt"
但是,这仅记录stdout
到test.txt
。它也不会记录stderr
。
显而易见的解决方案是使用如下所示的内容:
powershell ".\something.exe 2>&1 | tee test.txt"
但是,这不适用于所有something.exe
。有些something.exe
会将解释2>&1
为参数而失败。正确的解决方案是改为只在something.exe
和及其开关和参数周围加撇号,如下所示:
powershell ".\something.exe --switch1 --switch2 … arg1 arg2 …" 2>&1 | tee test.txt
'tee' is not recognized as an internal or external command
的原因很明显。使用2>&1
内部cmd线时,任何输出到stderr的命令都会导致Powershell错误。
我同意Brian Rasmussen的观点,unxutils端口是最简单的方法。在他的脚本页面的“ 批处理文件”部分中,Rob van der Woude提供了有关使用MS-DOS和CMD命令的大量信息。我以为他可能对您的问题有一个本机的解决方案,在那儿挖掘之后,我找到了TEE.BAT,这似乎是tee的MS-DOS批处理语言实现。这是一个看起来很复杂的批处理文件,我的倾向仍然是使用unxutils端口。
dir 1>a.txt 2>&1 | type a.txt
这将有助于重定向STDOUT和STDERR
我知道这是一个非常古老的话题,但是在以前的答案中,并没有完整实现用Batch编写的实时Tee。我下面的解决方案是一个Batch-JScript混合脚本,该脚本使用JScript部分只是从管道命令中获取输出,但是数据的处理是在Batch部分中完成的。这种方法的优点是任何批处理程序员都可以修改此程序以适合特定的需求。此程序还可以正确处理其他批处理文件生成的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");
file.exe 2>output.txt
file.exe 2>&1|tee.bat
的在这里找到:superuser.com/questions/452763/...
这是我根据其他答案之一使用的样本
@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
)
这样的事情应该满足您的需求?
%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
这是MTS 先前答案的变体,但是它添加了一些可能对其他人有用的功能。这是我使用的方法:
set _Temp_Msg_Cmd=
^
字符,使得命令不初步评价%~n0_temp.txt
使用命令行参数扩展语法 %~n0
获取批处理文件的名称。%~n0_log.txt
这是命令序列:
^> %~n0_temp.txt 2^>^&1
^& type %~n0_temp.txt ^>^> %~n0_log.txt
^& type %~n0_temp.txt
^& 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
这样,该命令就可以简单地附加在看上去更整洁的批处理文件中的后续命令之后:
echo test message %_Temp_Msg_Cmd%
也可以将其添加到其他命令的末尾。据我所知,当消息具有多行时,它将起作用。例如,如果出现错误消息,以下命令将输出两行:
net use M: /D /Y %_Temp_Msg_Cmd%
@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
这将创建一个具有当前日期时间的日志文件,您可以在此过程中使用控制台行
我使用带有“ 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
如果您使用的是CLI,为什么不使用FOR循环来“执行”您想要的任何事情:
for /F "delims=" %a in ('dir') do @echo %a && echo %a >> output.txt
Windows CMD上大量的用于循环的资源: https //ss64.com/nt/for_cmd.html 此处的关键是将分度数(delims)设置为零,该分度数会破坏输出的每一行。这样,它不会在默认的空白处中断。%a是一个任意字母,但是在“ do”部分中使用了它,以便...对每一行中解析的字符进行某些处理。在这种情况下,我们可以使用与号(&&)执行第二个echo命令,以创建或附加(>>)到我们选择的文件中。在编写文件时遇到问题时,更安全地保持DO命令的顺序,我们至少至少首先将回声发送到控制台。第一个echo前面的at符号(@)禁止控制台显示echo命令本身,而是仅显示命令的结果,即在%a中显示字符。
echo驱动器[x]中的
音量是Windows驱动器[x]中的音量是Windows
更新:/ F跳过空行,唯一的解决方法是对输出进行预过滤,在每行中添加一个字符(也许通过命令find使用行号)。在CLI中解决此问题并不快也不是很漂亮。另外,我没有包括STDERR,因此这里也捕获了错误:
for /F "delims=" %a in ('dir 2^>^&1') do @echo %a & echo %a >> output.txt
尖号(^)用来在它们后面转义符号,因为命令是一个正在被解释的字符串,而不是直接在命令行上输入它。
如果您希望在屏幕上真正看到某些内容,即使将批处理文件重定向到文件,也可以使用以下帮助。如果将设备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
另请参见良好的重定向说明:http : //www.p-dd.com/chapter7-page14.html
如何显示输出并将其重定向到文件。假设如果我使用dos命令dir> test.txt,则此命令会将输出重定向到文件test.txt而不显示结果。如何编写命令以显示输出并使用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.
这是实时的,但也很丑陋,性能很慢。没有经过良好测试:
@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
%MYCOMMAND%
完成并在许多情况下失败。它会跳过空行,行开始与;
失败,如内容<space>/<TAB>
,ON
,OFF
或/?
。但是其余的有时可能会起作用:-)
另一个变化是拆分管道,然后根据需要重新定向输出。
@echo off
for /f "tokens=1,* delims=:" %%P in ('findstr /n "^"') do (
echo(%%Q
echo(%%Q>&3
)
@exit/b %errorlevel%
将以上内容保存到.bat文件。它将文件流1上的文本输出也拆分为文件流3,您可以根据需要重定向。在下面的示例中,我将上面的脚本称为splitPipe.bat ...
dir | splitPipe.bat 1>con 2>&1 3>my_stdout.log
splitPipe.bat 2>nul < somefile.txt
c:\cygwin64\bin\script.exe
和输入cmd
和输入exit
和输入(退出Cygwin的CMD.EXE)exit
和输入(退出Cygwin的script.exe)