time
写入stderr
,因此有人认为添加2>&1
到命令行应该将其输出路由到stdout
。但这并不奏效:
test@debian:~$ cat file
one two three four
test@debian:~$ time wc file > wc.out 2>&1
real 0m0.022s
user 0m0.000s
sys 0m0.000s
test@debian:~$ cat wc.out
1 4 19 file
只有使用括号才有效:
test@debian:~$ (time wc file) > wc.out 2>&1
test@debian:~$ cat wc.out
1 4 19 file
real 0m0.005s
user 0m0.000s
sys 0m0.000s
在这种情况下为什么需要括号?为什么不被time wc
解释为一张单曲命令?
答案1
在ksh
, bash
and中zsh
,time
不是命令(是否内置),它是语言中的保留字,如for
or while
。
它用于对管道1进行计时。
在:
time for i in 1 2; do cmd1 "$i"; done | cmd2 > redir
您有特殊的语法告诉 shell 运行该管道:
for i in 1 2; do cmd1 "$i"; done | cmd2 > redir
并报告其时间统计数据。
在:
time cmd > output 2> error
是一样的,你也是定时该cmd > output 2> error
命令和计时统计信息仍然显示在 shell 的 stderr 上。
你需要:
{ time cmd > output 2> error; } 2> timing-output
或者:
exec 3>&2 2> timing-output
time cmd > output 2> error 3>&-
exec 2>&3 3>&-
为了将 shell 的 stderr 重定向到timing-output
time 构造之前(同样,不是命令)被使用(此处为时间cmd > output 2> error 3>&-
)。
您还可以time
在子外壳其 stderr 已重定向:
(time cmd > output 2> error) 2> timing-output
time
但是这个子 shell 在这里不是必需的,您只需要在调用该构造时重定向 stderr 即可。
大多数系统也有一个time
命令。您可以通过禁用该关键字来调用该time
关键字。您需要做的就是以某种方式引用该关键字,因为关键字只有在字面量时才会被识别。
'time' cmd > output 2> error-and-timing-output
但要注意格式可能不同,并且两者的 stderrtime
都会cmd
合并到error-and-timing-output
.
此外,time
与构造相反,命令time
不能对管道或复合命令或函数或 shell 内置函数进行计时...
如果它是内置命令,它可能能够对函数调用或内置命令进行计时,但无法对重定向、管道或复合命令进行计时。
1请注意bash
有(可以被视为)一个错误由此time (cmd) 2> file
(但不是time cmd | (cmd2) 2> file
例如)将计时输出重定向到file
答案2
没有名为 的命令time wc
,time
并且wc
是分开的单词在外壳中。
现在,经常有两个分开的程序name time
,一个是 shell 关键字,另一个是外部命令。在 shell 中,它time
是 shell 关键字,当您键入 时time wc ...
,shell 使用其关键字time
而不是外部时间效用。
当shell使用time
关键字时,不需要叉()新工艺中,现行time
标准和标准差没有变化。重定向部分位于:
time wc file > wc.out 2>&1
仅影响wc
。
当你使用复合命令(list)
:
(time wc file) > wc.out 2>&1
shelltime wc file
在子 shell 内运行,(time wc file)
被认为是单身的命令,重定向部分影响其标准输出和标准错误,现在包括time
和wc
。
您可以通过使用另一种形式的分组命令来实现相同的效果,而无需创建新进程的成本{list;}
:
{time wc file;} > wc.out 2>&1
如果您使用 external time
,那么您不会遇到这个问题,因为它是在新进程中运行的:
/usr/bin/time wc file > wc.out 2>&1
答案3
因为time
你正在执行的是 bash 内置的。 Bash 以这种特殊的方式处理它。
如果您将使用真正的time
二进制文件,它将完全按照您期望的方式运行:
/usr/bin/time wc file > wc.out 2>&1
虽然这次的输出有点不同:
$ /usr/bin/time wc file > wc.out
0.00user 0.00system 0:00.00elapsed ?%CPU (0avgtext+0avgdata1900maxresident)k
0inputs+8outputs (0major+82minor)pagefaults 0swaps
答案4
因为 time 是 shell 内置函数,所以它会写入壳的 stderr,而不是命令的 stderr。
使用括号强制将整个命令放入一个可以重定向 stderr 的子 shell 中。
使用大括号会产生类似的结果,而无需实际启动子 shell
{ time who ; } > /tmp/timwho >& /tmp/xx
(是的,你需要分号)