Windows 使用.bat文件的自定义T形三通命令

Windows 使用.bat文件的自定义T形三通命令,windows,batch-file,cmd,Windows,Batch File,Cmd,我试图使用为bat文件编写的代码,但在代码中实现它时遇到困难。我不想使用任何第三方安装来解决tee问题,因为如果我在一年内格式化计算机并想再次运行该程序,我希望代码能够正常工作 我以这种方式设置它: mycommand.exe | tee.bat -a output.txt 我尝试过使用一个单独的.bat文件,并尝试在原始.bat中包含一个函数(prefered),但没有成功: myprogram.exe |调用tee-a output.txt 回声。 回声。 回声。 SET/P restar

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

我以这种方式设置它:

mycommand.exe | tee.bat -a output.txt
我尝试过使用一个单独的
.bat
文件,并尝试在原始
.bat
中包含一个函数(prefered),但没有成功:

myprogram.exe |调用tee-a output.txt
回声。
回声。
回声。
SET/P restart=“是否再次运行?(1=是,2=否):”
如果“%restart%”==“1”转到LoopStart
::--------------------------------------------------------
:--函数部分从下面开始
::--------------------------------------------------------
:发球台
::检查Windows版本
如果不是“%OS%”==“Windows\u NT”转到语法
| 
::保持变量为局部变量
SETLOCAL
::检查命令行参数
SET Append=0
如果/I[%1]=[-a](
SET Append=1
移位
)
如果[%1]=[]转到语法
如果不是[%2]=[]转到语法
::测试无效的通配符
设置计数器=0
对于('DIR/A/B%1 2^>NUL')中的/F%%A,请调用:计数“%%~fA”
如果百分比计数器%GTR 1(
设置计数器=
转到语法
)
::似乎已指定有效的文件名
设置文件=%1
::检查指定名称的目录是否存在
目录/AD%文件%>NUL 2>NUL
如果不是错误级别1(
设置文件=
转到语法
)
::为Windows 2000/XP复制命令指定/Y开关
设置Y=
版本|查找“Windows NT”>NUL
如果错误级别1设置为Y=/Y
::刷新现有文件或创建新文件(如果未指定-a)
如果%Append%==0(复制%Y%NUL%文件%>NUL 2>&1)
::实际发球
对于/F“tokens=1*delims=]”中的%%A('FIND/N/V'')DO(
>CON回声%%B
>>%文件%ECHO.%%B
)
::完成
端部
后藤:EOF
:计数
设置/A计数器+=1
设置文件=%1
后藤:EOF
:语法
回声。
ECHO Tee.bat,适用于Windows NT 4/2000/XP的2.11a版
在屏幕上回显文本并同时将其重定向到文件
回声。
如果不是“%OS%”==“Windows\u NT”回显用法:some_命令△TEE.BAT[-a]文件名
如果不是“%OS%”==“Windows\u NT”转到跳过
ECHO用法:some_命令^ | TEE.BAT[-a]文件名
:跳过
回声。
ECHO其中:“some_command”是应该重定向其输出的命令
ECHO“filename”是输出应重定向到的文件
ECHO-a将命令的输出附加到文件中,
回显而不是覆盖文件
回声。
Rob van der Woude写的ECHO
回音http://www.robvanderwoude.com
Kees Couprie修改的ECHO
回音http://kees.couprie.org
埃科和安德鲁·卡梅隆
我正在尝试分割输出,以便在仍然能够与正在运行的程序交互的情况下,将控制台输出保存到文件中


如何使Tee命令与.bat一起正常工作,以便将输出拆分为文件和控制台。

由于Windows管道的工作方式,您尝试在管道内调用批处理函数的操作将始终失败-Windows通过新的CMD shell实例化管道的两侧。有关更多信息,请参阅

Rob van der Woude版本的批处理tee不可能适用于您,因为它使用
for/F
读取命令的结果-在读取任何行之前,必须执行该命令直到完成。如果在命令执行过程中需要用户交互,那么这将不起作用。使用该版本的tee,您还可以简单地将输出重定向到一个文件,然后在完成时键入该文件。显然不是你想要的

有一些纯批量技巧可以让你更接近,但我认为仍然有一个问题不能用纯批量解决。您的可执行文件可以在一行上放置提示,而不发出新行。我相信纯本机批处理总是读取整行(流结束时除外)。我不知道用批处理方法逐字读取

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

但是有一个简单的解决方案——JScript或VBScript的工作原理与champ类似,不需要任何特殊安装。这里是一个混合的JScript/批处理脚本,应该适合您。JScript编写得很糟糕,还有很多改进空间。例如,没有错误检查

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

@if(@X)=(@Y)@end/*开始JScript注释的混合行
:---JScript注释中调用内部JScript的批处理部分----
@回音
cscript//E:JScript//nologo“%~f0”%*
退出/b
-----JScript注释结束,正常JScript开始------------------*/
var fso=新的ActiveXObject(“Scripting.FileSystemObject”);
var模式=2;
如果(WScript.Arguments.Count()==2){mode=8;}
var out=fso.OpenTextFile(WScript.Arguments(0),mode,true);
var-chr;
而(!WScript.StdIn.AtEndOfStream){
chr=WScript.StdIn.Read(1);
WScript.StdOut.Write(chr);
out.Write(chr);
}
用法与您预期的非常相似。

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

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


更新

对于任何对批处理脚本有学术兴趣的人,我在DosTips上发布了一个纯本地批处理版本的tee。但这种混合方法是我首选的脚本编写方法
command.exe | tee.bat output.txt 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);
}