5 ms·
The reason 'time' is a builtin is because it can time a complete shell pipeline, not just a single command. If you type time foo |bar Then the result is t
by jimrandomh 10y ago
The reason 'time' is a builtin is because it can time a complete shell pipeline, not just a single command. If you type
time foo |bar
Then the result is the total time taken by foo and bar together. This requires it to have special-case syntax. Whereas
/usr/bin/time foo |bar
Would run foo and give its time statistics as input to bar.
- chubot 10y agoYes, as a consequence, it also lets you do this: time { sleep 0.1 sleep 0.2 } # result is 0.3 seconds which you obviously can't do with an external command. I wrote about that here: https://lobste.rs/s/hwgt2h/usr_bin_time_not_command_you_think_you_know https://lobste.rs/s/hwgt2h/usr_bin_time_not_command_you_thin...
- arthur2e5 10y agoThe `time` syntax in combination with for loops or just shell functions is pretty useful as well.
- ramshorns 10y agoIt looks like /usr/bin/time foo |bar would actually give the output of foo as input to bar, since the time statistics go to stderr.
- dotancohen 10y agoSince it is not an error, what we really need is a stdmeta file descriptor: http://unix.stackexchange.com/questions/197809/propose-additional-file-descriptor-stdmeta http://unix.stackexchange.com/questions/197809/propose-addit...
- easytiger 10y agoJust think of it as std dbg, not err
- eriknstr 10y agoI've been thinking a bit about this before and I think that not just one but a whole lot of additional streams would be useful. By default all commands would still use stdout and stderr only but you would be able to tell them to use other streams as well for their various data. Furthermore, each stream should be possible to pipe to a different process if you wish independently of the other streams. To a small degree this might be possible already with named pipes.
- MrQuincle 10y agoI just started playing around with IPC ideas with processes tellin each other which flags they would like: https://github.com/mrquincle/bipipes https://github.com/mrquincle/bipipes I think socket pairs would be great for it. Nothing implemented yet!
- Klathmon 10y agoHonestly this is one area where PowerShell kind of nailed it. I still don't use it enough, but when it comes to scripting PS's objects beat the hell out of these
- ncw33 10y agoIt is possible already - you can do `command 2>&4` to separate the output from one command in a pipeline into its own stream, then do `command2 <&4` to pull from the further down the pipeline.
- eriknstr 10y agoI would like more pipes for each process. This would allow many things, for example searching for multiple terms across all files in the whole file system in one go without opening each file more than once, and then grouping the different results together in accordance with the term that they matched.
- jcoffland 10y agoRun these commands for a better demonstration: time echo | sleep 1 vs. /usr/bin/time echo | sleep 1 The former times the entire pipeline whereas the later only times the first command in the pipe.
- fnord123 10y agoThis also gives the time of the entire pipeline (since the commands all begin together and only finish when the last command has completed): echo | /usr/bin/time sleep 1
- roblabla 10y agoI'm pretty sure this is wrong. As an example : sleep 2 | /usr/bin/time sleep 1 This gives an output of "1 second" even though the entire pipeline took 2 seconds.
- exprA 10y agoThe sleep sub-process of time is not part of the pipeline, however. It will exit after the requested time has passed.
- jstimpfle 10y agoThat is merely an optimization though. You can simply time sh -c 'foo | bar'
- therein 10y agoBut now you are timing the startup of `sh` as well.
- aexaey 10y ago...which (surprisingly) is a measurable amount. About 1 ms for `dash` and a whooping 9.5 ms for `bash` on a relatively slow CPU: pi@pi:~ $ time (for x in {1..1000}; do time echo | sleep 0.01; done 2>/dev/null) real 0m24.173s pi@pi:~ $ time (for x in {1..1000}; do time sh -c 'echo | sleep 0.01'; done 2>/dev/null) real 0m25.170s pi@pi:~ $ time (for x in {1..1000}; do time bash -c 'echo | sleep 0.01'; done 2>/dev/null) real 0m33.643s
- jstimpfle 10y ago1ms is on the order of process creation time, so not very relevant: The measured program itself requires process creation. Most programs run considerably longer than that (otherwise timing would not make much sense). It's really not more than that: an optimization.
- inetknght 10y ago`/usr/bin/time -o foo_time.txt foo | bar`
- Merovius 10y agoNo, it wouldn't require special-case syntax. It could just pass it's argument to '/bin/sh -c'. You'd have to shell-escape the pipeline, though.
- eridius 10y agoYeah it does require special-case syntax. When using bash's built-in time, the command is executed exactly the same way as if you weren't using time, which means the command can set variables or define functions in the current shell. For example, you can say time foo=bar echo $foo and it will correctly print out "bar". It can't do this if it executes the command in a subshell. Or similarly you can say `time cd /foo` and it will actually change the current working directory.
- floatboth 10y agoWow — that is extremely surprising. I did not expect that behavior at all. Who the hell thought it was a good idea to let a builtin command absorb the pipe symbol?!