为什么time ls | grep real
输出这个
real 0m0.002s
user 0m0.000s
sys 0m0.002s
而不仅仅是
real 0m0.002s
如果我输入
echo -e 'real\t0m0.002s\nuser\t0m0.000s\nsys\t0m0.002s\n' | grep real
我得到了我期望的结果,即
real 0m0.002s
我发现这有效
(time ls) 2>&1 > /dev/null | grep real
这个命令起什么作用?
答案1
为什么不能time ls | grep real
按预期工作。
time
是bash
保留字,其行为与 不同/usr/bin/time
。
如果时间保留字位于管道之前,则会报告其执行所消耗的时间以及用户和系统时间当管道终止时。
来源bash(1): GNU Bourne-Again SHell - Linux 手册页
此外,time
输出到标准错误而不是标准输出。
使用以下命令:
(time ls) 2>&1 >/dev/null | grep real
笔记:
(
和将和命令)
组合在一起(因此这些命令首先被评估)time
ls
2>&1 >/dev/null
首先将 stderr 重定向到 stdout (即管道),然后将 stdout 重定向到/dev/null
。因此 stderr 进入管道,而 stdout 则无处可去。
进一步阅读
- Linux 的 Bash 命令行的 AZ 索引- 与 Bash 命令行相关的所有事物的绝佳参考。
- 括号- 使用括号对表达式进行分组和扩展。
- 语法重定向- 重定向和进程替换。
- Bash 参考手册:重定向
- 图解重定向教程 [Bash Hackers Wiki]
答案2
是的,它可以工作,但是需要一点 I/O 重定向 :)
$ exec 3>&1 4>&2
{ time sleep 1 1>&3 2>&4; } 2>&1 |
grep 'real'
exec 3>&- 4>&-
输出 :
real 0m1,003s
一个相当简单的方法:
$ TIMEFORMAT=%R
$ time sleep 1
1,003
答案3
这里有两个问题。
首先也是最重要的,“时间”将其输出发送到 stderr(标准错误)而不是 stdout,这样除非采取特殊措施,否则它不会被正常的重定向命令捕获。
其次,time 不是一个普通的程序,而是一个由 shell 直接解释的特殊内置命令(适用于 bash、csh、tcsh 等 shell)。因此,它以非标准方式工作,并对命令行的其余部分进行计时(除非您使用的是非常不常见的 shell)。
因此,为了获得想要的结果(使用 bash),您需要使用:
(time ls) 2>&1 | grep real
这将在子 shell 中运行“ls”并对其进行计时[(时间 ls)],将标准错误发送到标准输出[ 2>&1 ],然后将标准发送到“grep”[|grep]。
您使用的最后一部分“>?dev/null”会丢弃 ls 命令本身的正常输出,以防其中包含单词“real”。
答案4
看来time
直接写入控制台而不是stdout
,这意味着添加不会影响命令或管道的输出time
。
因此永远不会看到时间报告,因为整个管道都是计时的,grep
所以无论如何它都是在完成后生成的。grep