为了账号安全,请及时绑定邮箱和手机立即绑定

对.bat文件使用定制的Tee命令

/ 猿问

对.bat文件使用定制的Tee命令

慕仰8121524 2019-10-30 14:42:13

我正在尝试使用为bat文件编写的T恤代码,但是在我的代码中无法实现它。我不想使用任何第三方安装来解决上述问题,因为如果我一年内格式化计算机并希望再次运行该程序,我希望代码能够正常工作。


我以这种方式设置它:


mycommand.exe | tee.bat -a output.txt

我尝试过使用单独的.bat文件,并尝试在原始文件中包含(以功能形式).bat无济于事:


myprogram.exe | call tee -a output.txt

echo.

echo.

echo.

SET /P restart="Do you want to run again? (1=yes, 2=no): "

if "%restart%"=="1" GOTO LoopStart



::--------------------------------------------------------

::-- Function section starts below here

::--------------------------------------------------------

:tee

:: Check Windows version

IF NOT "%OS%"=="Windows_NT" GOTO Syntax

:: Keep variables local

SETLOCAL


:: Check command line arguments

SET Append=0

IF /I [%1]==[-a] (

    SET Append=1

    SHIFT

)

IF     [%1]==[] GOTO Syntax

IF NOT [%2]==[] GOTO Syntax


:: Test for invalid wildcards

SET Counter=0

FOR /F %%A IN ('DIR /A /B %1 2^>NUL') DO CALL :Count "%%~fA"

IF %Counter% GTR 1 (

    SET Counter=

    GOTO Syntax

)


:: A valid filename seems to have been specified

SET File=%1


:: Check if a directory with the specified name exists

DIR /AD %File% >NUL 2>NUL

IF NOT ERRORLEVEL 1 (

    SET File=

    GOTO Syntax

)


:: Specify /Y switch for Windows 2000 / XP COPY command

SET Y=

VER | FIND "Windows NT" > NUL

IF ERRORLEVEL 1 SET Y=/Y


:: Flush existing file or create new one if -a wasn't specified

IF %Append%==0 (COPY %Y% NUL %File% > NUL 2>&1)


:: Actual TEE

FOR /F "tokens=1* delims=]" %%A IN ('FIND /N /V ""') DO (

    >  CON    ECHO.%%B

    >> %File% ECHO.%%B

)


:: Done

ENDLOCAL

GOTO:EOF



:Count

SET /A Counter += 1

SET File=%1

GOTO:EOF



:Syntax

ECHO.

ECHO Tee.bat,  Version 2.11a for Windows NT 4 / 2000 / XP

ECHO Display text on screen and redirect it to a file simultaneously

ECHO.

IF NOT "%OS%"=="Windows_NT" ECHO Usage:  some_command  ¦  TEE.BAT  [ -a ]  filename

IF NOT "%OS%"=="Windows_NT" GOTO Skip

ECHO Usage:  some_command  ^|  TEE.BAT  [ -a ]  filename

:Skip

ECHO.

我正在尝试分割输出,以便可以将控制台输出保存到文件中,同时仍然能够与正在运行的程序进行交互。


我如何才能使Tee命令与.bat一起正常使用,以便可以将输出分为文件和控制台。


查看完整描述

3 回答

?
Cats萌萌

由于Windows管道的工作方式,您在管道中调用批处理函数的尝试将始终失败-Windows通过新的CMD Shell实例化管道的两侧。有关更多信息,请参见https://stackoverflow.com/a/8194279/1012053。


批处理tee的Rob van der Woude版本可能无法为您工作,因为它使用a FOR /F来读取命令的结果-该命令必须执行到完成才能读取任何行。如果您在命令执行期间需要用户交互,那将不起作用。使用该版本的tee,您还可以简单地将输出重定向到文件,然后TYPE在完成后将文件重定向。显然不是您想要的。


有一些纯批处理技巧可以使您更接近,但我认为纯批处理仍无法解决一个问题。您的可执行文件可能会在一行上显示提示,而不会发出新行。我相信纯本地批处理总是读取整行(流末尾除外)。我不知道一种逐字符读取的批处理方法。


轻微校正 -SET /P可以读取管道输入的部分行,但是它有一些局限性,无法将其用于可靠的批处理三通解决方案:无法确定每行何时结束。每条“行”限制为1021个字符。它从每条“行”的末尾剥离控制字符。无法确定何时到达输入流的末尾。


但是,有一个简单的解决方案-JScript或VBScript就像冠军一样,不需要任何特殊的安装。这是一个适合您的混合JScript /批处理脚本。JScript编写得很差,还有很多改进的余地。例如,没有错误检查。


我将脚本另存为tee.bat。第一个必需参数指定要写入的文件的名称。默认情况下,该文件将被覆盖(如果已存在)。如果提供了第二个参数(值无关紧要),则将输出附加到文件中。


@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment


::--- Batch section within JScript comment that calls the internal JScript ----

@echo off

cscript //E:JScript //nologo "%~f0" %*

exit /b


----- End of JScript comment, beginning of normal JScript  ------------------*/

var fso = new ActiveXObject("Scripting.FileSystemObject");

var mode=2;

if (WScript.Arguments.Count()==2) {mode=8;}

var out = fso.OpenTextFile(WScript.Arguments(0),mode,true);

var chr;

while( !WScript.StdIn.AtEndOfStream ) {

  chr=WScript.StdIn.Read(1);

  WScript.StdOut.Write(chr);

  out.Write(chr);

}

使用情况几乎与您期望的一样。


command.exe | tee.bat output.txt 1

最后一个参数强制附加模式。它可以是除1之外的任何值


您可以按照自己的喜好将所有内容放入一个批处理脚本中。


@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment


::--- Batch section within JScript comment ----------------------------

@echo off


::This block of code handles the TEE by calling the internal JScript code

if "%~1"=="_TEE_" (

  cscript //E:JScript //nologo "%~f0" %2 %3

  exit /b

)


::The rest of your batch script goes here


::This pipes to TEE in append mode

mycommand.exe | "%~f0" _TEE_ output.txt 1


exit /b


----- End of JScript comment, beginning of normal JScript  ------------------*/

var fso = new ActiveXObject("Scripting.FileSystemObject");

var mode=2;

if (WScript.Arguments.Count()==2) {mode=8;}

var out = fso.OpenTextFile(WScript.Arguments(0),mode,true);

var chr;

while( !WScript.StdIn.AtEndOfStream ) {

  chr=WScript.StdIn.Read(1);

  WScript.StdOut.Write(chr);

  out.Write(chr);

}

更新资料


对于那些对批处理脚本有学术兴趣的人,我在DosTips的异步本机批处理tee脚本上发布了纯tee的本机批处理版本。但是这种混合方法是我首选的脚本解决方案。


查看完整回答
反对 2019-10-30
?
湖上湖

不错,只有一部分I believe pure native batch always reads entire lines是错误的,我在一些多线程批处理中使用了它 

查看完整回答
反对 2019-10-30
?
慕田峪9158850

这对我有用。您确定mycommand.exe输出到stdout而不是stderr吗?要捕获后者,您需要mycommand.exe 2>&1 | call tee ... 

查看完整回答
反对 2019-10-30
  • 3 回答
  • 0 关注
  • 344 浏览

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信