viu*_*ser 18 io-redirection shell-builtin
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
Run Code Online (Sandbox Code Playgroud)
只有括号才有效:
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
Run Code Online (Sandbox Code Playgroud)
为什么在这种情况下需要括号?为什么不被time wc
解释为一个单一的命令?
Sté*_*las 24
In ksh
, bash
and zsh
,time
不是命令(内置与否),它是语言中的保留字,如for
or while
。
它用于为管道计时1。
在:
time for i in 1 2; do cmd1 "$i"; done | cmd2 > redir
Run Code Online (Sandbox Code Playgroud)
您有特殊的语法告诉 shell 运行该管道:
for i in 1 2; do cmd1 "$i"; done | cmd2 > redir
Run Code Online (Sandbox Code Playgroud)
并为其报告计时统计信息。
在:
time cmd > output 2> error
Run Code Online (Sandbox Code Playgroud)
这是相同的,你定时的cmd > output 2> error
命令,而计时统计信息仍然在 shell 的 stderr 上进行。
你需要:
{ time cmd > output 2> error; } 2> timing-output
Run Code Online (Sandbox Code Playgroud)
或者:
exec 3>&2 2> timing-output
time cmd > output 2> error 3>&-
exec 2>&3 3>&-
Run Code Online (Sandbox Code Playgroud)
为了timing-output
在使用 time 构造(再次,不是command)之前将 shell 的 stderr 重定向到(这里是 timecmd > output 2> error 3>&-
)。
您还可以time
在其 stderr 重定向的子shell中运行该构造:
(time cmd > output 2> error) 2> timing-output
Run Code Online (Sandbox Code Playgroud)
但是这里不需要该子shell,您只需要在time
调用构造时重定向stderr 。
大多数系统也有一个time
命令。您可以通过禁用time
关键字来调用那个。您需要做的就是以某种方式引用该关键字,因为关键字仅在文字时才被识别。
'time' cmd > output 2> error-and-timing-output
Run Code Online (Sandbox Code Playgroud)
但请注意格式可能不同,并且两者的 stderrtime
和cmd
将被合并到error-and-timing-output
.
此外,与构造time
相反,命令time
不能为管道或复合命令或函数或 shell 内置程序计时......
如果它是一个内置命令,它可能能够为函数调用或内置命令计时,但它不能为重定向、管道或复合命令计时。
1请注意,bash
有(可以被视为)一个错误,即time (cmd) 2> file
(但不是time cmd | (cmd2) 2> file
例如)将计时输出重定向到file
没有名为time wc
,的命令,time
并且在 shell 中wc
是分隔的单词。
现在,通常有两个独立的程序名为time
,一个是 shell 关键字,另一个是外部命令。在time
作为 shell 关键字的 shell 中,当您键入 时time wc ...
,shell 使用其关键字time
而不是外部时间实用程序。
shell 使用time
关键字时,不需要fork()新进程,当前time
标准 in 和标准错误不会改变。重定向部分在:
time wc file > wc.out 2>&1
Run Code Online (Sandbox Code Playgroud)
wc
只影响。
当您使用复合命令时(list)
:
(time wc file) > wc.out 2>&1
Run Code Online (Sandbox Code Playgroud)
shelltime wc file
在子shell 中运行,(time wc file)
被视为单个命令,重定向部分影响其标准输出和标准错误,现在包括time
和wc
.
您可以通过使用另一种形式的分组命令来实现相同的效果,而无需分叉新进程{list;}
:
{time wc file;} > wc.out 2>&1
Run Code Online (Sandbox Code Playgroud)
如果使用 external time
,则不会遇到此问题,因为它是在新进程中运行的:
/usr/bin/time wc file > wc.out 2>&1
Run Code Online (Sandbox Code Playgroud)