1

Why this doesn't work?

$ time sleep 1 2>&1 | grep real

real    0m1.003s
user    0m0.007s
sys 0m0.001s

$ ofile=time.out
$ for x in {1..2}; do time sleep 1 ${x}> ${ofile} && test -s ${ofile} && echo '## OK' || echo '## NOK'; done

real    0m2.002s
user    0m0.002s
sys 0m0.000s
## NOK

real    0m3.002s
user    0m0.002s
sys 0m0.000s
## NOK

According to man time:

When command finishes, time writes a message to standard error giving timing statistics about this program run.

Where did I get it wrong? It also seems weird that with each iteration time grows?

$ command -V time
time is a shell keyword

$ echo $SHELL
/bin/bash

$ bash --version
GNU bash, version 4.4.12(1)-release (x86_64-unknown-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

EDIT

I tried what was suggested in the comments:

$ command time sleep 1
bash: time: command not found

Also tested it on the Debian9 system:

$ command -V time 
time is a shell keyword

$ command time sleep 1
0.00user 0.00system 0:01.00elapsed 0%CPU (0avgtext+0avgdata 1844maxresident)k
0inputs+0outputs (0major+76minor)pagefaults 0swaps

$ time sleep 1 |& grep real

real    0m1.001s
user    0m0.000s
sys 0m0.000s

$ bash --version
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
  • The bash time builtin appears to output directly to your tty: this still shows output: time sleep 1 >/dev/null 2>&1 -- try using the time command: command time sleep 1 2>output.file – glenn jackman Aug 24 '17 at 23:04
  • Please see edits – NarūnasK Aug 24 '17 at 23:25
  • For bash builtins, use help not man. help time will tell you that the whole pipeline is measured. That's why you can not catch its result by piping through grep, unless using braces or parentheses like Stephen Harris did in his answer. – xhienne Aug 25 '17 at 0:01
4

Your command time sleep 1 ${x} effectively runs time sleep 1 1 and then time sleep 1 2.

The bash builtin time command takes those two values and sleeps for both of them.

So sleep 1 1 is the same as sleep 2 and sleep 1 2 is the same as sleep 3.

With the builtin time command, things don't quite work the same way as normal and so time sleep 2>... is interpreted closer to time ( sleep 2>...).

So instead

( time sleep 1 ) 2>&1 | grep real
| improve this answer | |
  • Just curious, did you came to conclusion of time sleep 1 1 by trying something like set -x x=1; time sleep 1 ${x}> test, or there's something that I don't understand about Bash? – NarūnasK Aug 25 '17 at 1:06
  • 1
    Hmm, your loop sets x=1 then x=2 and ${x} is set each time. So it's literally running sleep 1 1 then sleep 1 2. That's just how loops work. For example; for a in hello there; do echo ${a}; done will return two lines; "hello" and "there". Your loop is just the same. – Stephen Harris Aug 25 '17 at 2:25
  • But why it does not redirect ${x}> properly? So in the first iteration it should be 1> file (file descriptor 1 STDOUT to file), in the other iteration it should be 2> file (file descriptor 2 STDERR to file), or is it not possible to specify file descriptors in the variable? Also in your answer you show time sleep 2>..., when it actually should be time sleep 1 2>... – NarūnasK Aug 25 '17 at 9:42
  • That's just not how shell parsing works. – Stephen Harris Aug 25 '17 at 10:10
  • Can you elaborate more, why in this situation setting file descriptor in the variable does not work? – NarūnasK Aug 27 '17 at 21:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.