147

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

例如:

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

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

4

12 回答 12

227

不,您不能使用纯重定向。
但是通过一些技巧(比如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ávio Décio 和 andynormancx 的例子行不通。

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

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

command 1>&1
dir 1>&2

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

希望能帮助到你。

于 2011-01-03T20:34:58.123 回答
34

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

mycommand > tee outpu_file.txt

如果您还需要 STDERR 输出,请使用以下内容。
2>&1STDERR 输出组合到 STDOUT(主流)中。

mycommand 2>&1 | tee output_file.txt
于 2011-10-29T18:57:55.660 回答
11

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

type windows-dir.txt

在那条线之后。

于 2009-02-02T16:42:41.617 回答
8

对我有用的解决方案是:dir > a.txt | 输入 a.txt

于 2009-07-17T07:27:07.330 回答
7

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

@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
于 2015-01-05T01:56:54.917 回答
3
command > file >&1
于 2009-02-02T16:41:38.390 回答
2

如果要追加而不是替换输出文件,您可能需要使用

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

或者

dir 1>> files.txt 2>>&1
于 2016-06-15T12:33:05.403 回答
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

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

于 2017-02-25T22:59:05.967 回答
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

这是包含 Tee.exe 的存储库,以防您没有编译工具 https://github.com/iamshiao/Tee

于 2018-05-27T09:47:25.767 回答
1

我喜欢 atn 的回答,但对我来说下载它并不像 wintee 那样简单它也是开源的,只提供 tee 功能(如果你只想要 tee 而不是整套 unix 实用程序,这很有用)。我从 davor 对Displaying Windows command prompt output and redirecting it to a file的回答中了解到这一点,您还可以在其中找到对 unix 实用程序的引用。

于 2013-03-08T16:24:49.930 回答
0

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

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

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

于 2016-04-06T00:32:37.380 回答
-2

我想你想要这样的东西:

echo Your Msg> YourTxtFile.txt

或者如果你想要一个新行:

echo Your Msg>> YourTxtFile.txt

这些命令非常适合日志。

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

另注:如果文件不存在,则会创建文件。

于 2020-01-20T14:06:56.213 回答