如何在bat脚本中回显控制台输出并将其发送到文件?


136

我有一个执行任务的批处理脚本,并将输出发送到文本文件。有没有办法在控制台窗口上也显示输出?

例如:

c:\Windows>dir > windows-dir.txt

有没有办法dir在控制台窗口中显示输出并将其输出到文本文件中?


下面说明了您可以进行的重定向以及一些示例。<br>希望对您有所帮助:)
emoSTN 2012年


请注意,@ Vadzim,2009年2月2日16:38提出的问题不能被视为与三个月后的2009年4月28日06:32提出的问题的重复。
Compo

Answers:


216

不,您不能使用纯重定向。
但是,您可以使用一些技巧(例如tee.bat)。

我尝试解释一下重定向。

使用> file<file重定向十个流之一。
如果重定向是在命令之前还是之后,则这并不重要,因此这两行几乎相同。

dir > file.txt
> file.txt dir

在此示例中,重定向仅是1>的快捷方式,这意味着将对流1(STDOUT)进行重定向。
因此,您可以在任何流之前添加数字,例如2> err.txt,也可以在一行中重定向多个流。

dir 1> files.txt 2> err.txt 3> nothing.txt

在此示例中,“标准输出”将进入files.txt,所有错误将在err.txt中,stream3将进入nothing.txt(DIR不使用流3)。
Stream0是STDIN
Stream1是STDOUT Stream2
是STDERR
Stream3-9未使用

但是,如果您尝试多次重定向同一流,会发生什么情况?

dir > files.txt > two.txt

“只能有一个”,它永远是最后一个!
因此等于dir> two.txt

好的,还有一种可能,将一个流重定向到另一个流。

dir 1>files.txt 2>&1 

2>&1将stream2重定向到stream1,而1> files.txt将所有都重定向到files.txt
这里的顺序很重要!

dir ... 1>nul 2>&1
dir ... 2>&1 1>nul

是不同的。第一个将所有(STDOUT和STDERR)重定向到NUL,
但是第二行将STDOUT重定向到NUL,将STDERR重定向到“空” STDOUT。

作为一个结论,很明显为什么OtávioDécio和andynormancx的示例无法正常工作。

command > file >&1
dir > file.txt >&2

两者都尝试将stream1重定向两次,但是“只能有一个”,并且它始终是最后一个。
所以你得到

command 1>&1
dir 1>&2

并且在第一个示例中,不允许将stream1重定向到stream1(并且不是很有用)。

希望能帮助到你。


24
因此,使用本地Windows Shell是不可能的
幻想曲2014年

7
@fantastory有可能看到dbenham Windows批处理的
jeb 2014年

97
我不敢相信我只是阅读了整篇文章,发现整件事可以总结为“否”。
查尔斯·麦克凯维

1
第二种机制“句柄重复”又如何呢?我尝试过3<&2(请注意LT而不是GT),然后进行3>errors.txt。但这很糟糕地结束了-所有后续的stderr输出都被捕获到了errors.txt(也就是说-也从其他命令!)。
Tomasz Gandor

您可以使用for /f "delims=" %%v in ('dir') do echo %%v>>file.txt
scriptmastere02 '18

32

只需以这种方式使用Windows版本的UNIX tee命令(可从http://unxutils.sourceforge.net找到):

mycommand > tee outpu_file.txt

如果您还需要STDERR输出,请使用以下命令。
2>&1结合了stderr输出到STDOUT(一次流)。

mycommand 2>&1 | tee output_file.txt

3
PowerShell的三通对象提供类似的功能。获取流程| Tee对象文件c:\ scripts \ test.txt
Kevin Obee,2016年

我在powershell和常规shell中都尝试过。1>tee a.txt将stdout重定向到名为的文件,tee而不是调用tee命令。谁能确认这个答案对他们有用?
mafu

@mafu我可以确认这一点。
塞诺

@mafu上面的答案有点不正确。您必须使用管道“ |” 而不是顶部示例中的“>”。奇怪的是,在这种情况下,STDOUT和STDERR输出的顺序在命令行上混合了。最下面的例子对我来说是完美的。
塞诺

另外,sourceforge下载对我来说还是坏了。我在这里找到了另一台主机:wzw.tum.de/public-html/syring/win32/UnxUtilsDist.html(慕尼黑大学)
塞诺

9

如果您不需要实时输出(即程序编写时),则可以添加

type windows-dir.txt

在那条线之后。


或在同一直线上(在提示符是有用的): dir > windows-dir.txt & type windows-dir.txt。这也适用于块:( echo %date% <NL> echo %username% <NL> echo %time% <NL> pause>CON )>test.txt & type test.txt。但是,如果需要实时输出,则可以为此使用tee工具的Windows端口…
mousio 2011年


6

是的,有一种方法可以在控制台(屏幕)和文件中显示单个命令输出。使用您的示例,使用...

@ECHO OFF
FOR /F "tokens=*" %%I IN ('DIR') DO ECHO %%I & ECHO %%I>>windows-dir.txt

详细说明:

FOR命令将命令或文本的输出解析为一个变量,可以多次引用该变量。

对于诸如的命令,请DIR /B用单引号引起来,如下例所示。将DIR /B文本替换为所需的命令。

FOR /F "tokens=*" %%I IN ('DIR /B') DO ECHO %%I & ECHO %%I>>FILE.TXT

要显示文本,请用双引号引起来,如下例所示。

FOR /F "tokens=*" %%I IN ("Find this text on console (screen) and in file") DO ECHO %%I & ECHO %%I>>FILE.TXT

...以及换行...

FOR /F "tokens=*" %%I IN ("Find this text on console (screen) and in file") DO (
  ECHO %%I & ECHO %%I>>FILE.TXT
)

如果您有时只希望在控制台(屏幕)上输出,而有时只希望将输出发送到文件,而有时又希望同时发送给两个文件,请使用变量指定FOR循环的“ DO”子句,如下所示%TOECHOWHERE%

@ECHO OFF
FOR %%I IN (TRUE FALSE) DO (
  FOR %%J IN (TRUE FALSE) DO (
    SET TOSCREEN=%%I & SET TOFILE=%%J & CALL :Runit)
)
GOTO :Finish

:Runit
  REM Both TOSCREEN and TOFILE get assigned a trailing space in the FOR loops
  REM above when the FOR loops are evaluating the first item in the list,
  REM "TRUE".  So, the first value of TOSCREEN is "TRUE " (with a trailing
  REM space), the second value is "FALSE" (no trailing or leading space).
  REM Adding the ": =" text after "TOSCREEN" tells the command processor to
  REM remove all spaces from the value in the "TOSCREEN" variable.
  IF "%TOSCREEN: =%"=="TRUE" (
      IF "%TOFILE: =%"=="TRUE" (
          SET TEXT=On screen, and in "FILE.TXT"
          SET TOECHOWHERE="ECHO %%I & ECHO %%I>>FILE.TXT"
        ) ELSE (
          SET TEXT=On screen, not in "FILE.TXT"
          SET TOECHOWHERE="ECHO %%I"
      )
    ) ELSE (
      IF "%TOFILE: =%"=="TRUE" (
          SET TEXT=Not on screen, but in "FILE.TXT"
          SET TOECHOWHERE="ECHO %%I>>FILE.txt"
        ) ELSE (
          SET TEXT=Not on screen, nor in "FILE.TXT"
          SET TOECHOWHERE="ECHO %%I>NUL"
      )
  )
  FOR /F "tokens=*" %%I IN ("%TEXT%") DO %TOECHOWHERE:~1,-1%
GOTO :eof

:Finish
  ECHO Finished [this text to console (screen) only].
  PAUSE

您应该delims=改用。
scriptmastere02 '18

3
command > file >&1

当您不将数据写到屏幕上时,它的速度更快,因为您没有用废话填满缓冲区,而是让批处理作业运行。如果您正在调试,则不会使用>文件语法。
随机开发商

@andynormancx yup忘记键入该内容,而不是从CMD中剪切并粘贴。
随机开发商

我无法在Windows命令提示符下使用该语法,而是使用了type命令。
JamesEggers

&2确实可以正常工作,但是在我测试该文件时现在尚未创建该文件。
JamesEggers

5
如果我执行“ dir> file.txt>&2”,则不会创建file.txt。在控制台中回显目录的输出,但未创建文件。不存在“>&2”时创建文件。
JamesEggers

2

如果要附加而不是替换输出文件,则可能要使用

dir 1>> files.txt 2>> err.txt

要么

dir 1>> files.txt 2>>&1

2

我的选择是:

创建一个接收消息的子例程,并自动将其发送到控制台和日志文件的过程。

setlocal
set logfile=logfile.log

call :screenandlog "%DATE% %TIME% This message goes to the screen and to the log"    

goto :eof

:screenandlog
set message=%~1
echo %message% & echo %message% >> %logfile%
exit /b

如果将变量添加到消息中,请确保在将其发送到子例程之前先删除其中的引号,否则它可能会使您的批处理陷入困境。当然,这仅适用于回声。


哇!我真的很喜欢!不过,我进行了三处更改,希望您喜欢它们。 1)我使用setlocal enabledelayedexpansion,而不是仅仅setlocal 2)我使用延迟扩展为日志文件的变量,因此>> !logfile!,而不是>> %logfile%内的子程序。这样,当从代码块中调用时(例如在if语句中),它就可以工作。3)我删除了“设置消息”行,因为不需要多余的变量。我们已经有它了,$~1所以我都echo $~1为两个echo命令。
Nate

2

我制作了一个简单的C#控制台,该控制台可以处理cmd屏幕和日志的实时输出

class Tee
{
    static int Main(string[] args)
    {
        try
        {
            string logFilePath = Path.GetFullPath(args[0]);

            using (StreamWriter writer = new StreamWriter(logFilePath, true))
            {
                for (int value; (value = Console.In.Read()) != -1;)
                {
                    var word = Char.ConvertFromUtf32(value);
                    Console.Write(word);
                    writer.Write(word);
                }
            }
        }
        catch (Exception)
        {
            return 1;
        }
        return 0;
    }
}

批处理文件的用法与您使用Unix的方法相同 tee

foo | tee xxx.log

如果您没有用于编译https://github.com/iamshiao/Tee的工具,则这里是包含Tee.exe的存储库



0

“ Tomas R”提供的解决方案非常适合OP的问题,它本身就可用。

尝试:chkdsk c:> output.txt | 输入output.txt

该命令的输出涉及一个完成百分比,该完成百分比会串行输出到文件中,因此它看起来会有些混乱(即,文本将在执行过程中追加)。输出到STDOUT(屏幕)的位不会发生这种情况。如果只执行相同的命令而不进行重定向,将会是这样。


-3

我认为您需要与此类似的东西:

echo Your Msg> YourTxtFile.txt

或者,如果您要换行:

echo Your Msg>> YourTxtFile.txt

这些命令非常适合日志。

注意:这有时会出现故障并替换我计算机上的整个文本文件。

另请注意:如果文件不存在,它将创建文件。


1
不,OP希望将输出保存到文件中并显示在屏幕上。您的只是写入文件。(和>设计以覆盖该文件使用。>>追加
斯蒂芬
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.