首先,您需要一个批处理文件,例如:
add_ts.bat
@for /F "usebackq delims==" %%i in (`%1`) do @echo %time% %%i
你会像这样运行:
add_ts.bat "make all -d --trace" > buildlog.txt
但是,如果您想捕获和
时间戳STDERR 以及STDOUT 来自传递的命令
%1,因为%1 周围的反引号运算符只会捕获STDOUT
要解决此问题,您需要在反引号中捕获 STDERR 和 STDOUT,方法是在其中使用重定向,这反过来意味着
你需要运行一个子shell来理解重定向,和你需要
转义重定向操作符,这样它们就不会被顶层解释
贝壳。这一切都来了:
@for /F "usebackq delims==" %%i in (`cmd /C %1 2^>^&1`) do @echo %time% %%i
以同样的方式运行。
稍后
我不明白为什么 |本身不足以将 STDOUT 和 STDERR 发送到 add_ts.bat 的 STDIN
是。我认为您是在两种误解的结合下工作的。
一:您认为程序的命令行参数与其标准相同
输入,或者它从其标准输入中获取命令行参数。它没有。
程序的命令行参数(如果有)作为固定列表传递给它
程序启动协议中的字符串。它的标准输入是一个输入流
操作系统同时可用,并默认连接到程序所在的控制台
开始。这个默认值可以在 shell 中被重定向操作符覆盖。该输入流的内容不是预先固定的。它会喂给
只要程序正在运行,无论何时输入到控制台或来自其重定向代理的程序,程序都会读取它。该程序
可以解析或忽略其命令行参数,并且完全独立于此,它可以读取或忽略其标准输入。
您的程序add_ts.bat 是一个解析其第一个命令行参数的程序
- 它使用%1 - 并且不再理会。它完全忽略了它的标准输入。
二:您认为管道的效果,例如
a | b
是启动一个a 进程,然后,对于它写入标准输出的每一行,启动
一个独特的b 进程,它将自动接收a 写的一行
一个 single 命令行参数(不管一行中有多少单词)并做它的事情
使用那个单一的命令行参数。
事实并非如此。操作系统启动一个a进程和一个b进程,并连接
一个a 进程的标准输出到一个b 进程的标准输入。为了
要工作的管道,b 必须是一个程序读取其标准输入。您的
add_ts.bat 不是这样的程序。它只是一个解析其第一个命令行的程序
参数:| 没有给出任何参数,命令行:
make all --trace -d 2>&1 | add_ts.bat
也不给它。命令行:
make all --trace -d 2>&1 | add_ts.bat "Hello World"
会给它一个命令行参数并且:
make all --trace -d 2>&1 | add_ts.bat Hello World
会给它两个,不是一个,命令行参数,第二个被忽略。但无论如何
它不读取它的标准输入,所以管道到它是徒劳的。
网站 ss64.com 非常适合 CMD redirection and piping
但它假设您知道程序必须做什么才能成为可流水线命令:成为上游命令,
它必须写出它的标准输出;要成为下游命令,它必须读取其标准输入。