在文件中写入`time`的输出,为什么需要括号?

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, bashand zsh,time不是命令(内置与否),它是语言中的保留字,如foror 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)

但请注意格式可能不同,并且两者的 stderrtimecmd将被合并到error-and-timing-output.

此外,与构造time相反,命令time不能为管道或复合命令或函数或 shell 内置程序计时......

如果它是一个内置命令,它可能能够为函数调用或内置命令计时,但它不能为重定向、管道或复合命令计时。


1请注意,bash有(可以被视为)一个错误,即time (cmd) 2> file(但不是time cmd | (cmd2) 2> file例如)将计时输出重定向到file


cuo*_*glm 7

没有名为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)被视为单个命令,重定向部分影响其标准输出和标准错误,现在包括timewc.


您可以通过使用另一种形式的分组命令来实现相同的效果,而无需分叉新进程{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)