28
$ time if [[ $dir2 -ot $dir1 ]] ; then open $dir2 ; else open $dir1 ; fi
real    0m0.055s
user    0m0.023s
sys     0m0.018s

$ time  [[ $dir2 -ot $dir1 ]] && open $dir2 || open $dir1
real    0m0.000s
user    0m0.000s
sys     0m0.000s

At above, I compared two methods for testing which directory is older and then opening the older directory. I guess I'm just confused why the && and || operators right after a test has the same functionality of an if/then test, and why it's faster. Are there advantages/disadvantages to each?

αғsнιη
  • 41,407
cp10111
  • 297

1 Answers1

70

time always times the directly following pipeline.

A pipeline is a sequence of one or more commands (simple or compound) separated by one of the control operators | or |&.

if ... fi is a single compound command, and [[ ... ]] is one command. The part after && is not measured by time because foo && bar is a list of commands.

Compare:

$ time if true; then sleep 1; fi

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

$ time true && sleep 1

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

example of pipeline separated with |:

$ time true | sleep 1

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

To measure time from all of the second commands, you can group them by putting it in (curly) brackets:

$ time { true && sleep 1; }

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

ilkkachu
  • 138,973
pLumo
  • 22,565
  • 5
    Good catch! The time keyword only applies to the command (compound or simple) that it precedes. So to time properly in the second command, they would need to use time open ... || time open .... – Kusalananda Jun 25 '20 at 16:33
  • 11
    To be hideously exact, Bash's time times a pipeline, which can then contain simple or compound commands. if-then-fi is a compound command, which can be part of a pipeline, but foo && bar is a list of commands that can't be without being grouped in { } or ( ). – ilkkachu Jun 25 '20 at 16:44
  • 1
    Try command time ... ;) – 0xC0000022L Jun 26 '20 at 10:00
  • The [ : ] construct is completely different from just :. : is a command that simply exits with 0 (true) status (also called true). The [ is another command that runs various tests, by default testing whether the argument is non-empty (which : is). If called with the name [, rather than the alternate name test, it requires an additional ] argument. – Jan Hudec Jun 26 '20 at 10:59
  • @JanHudec, yes, though in practice they both return a truthy exit status, so it doesn't matter here. The time taken by both is also insignificant with the sleep 1 right there next to them. – ilkkachu Jun 26 '20 at 12:24
  • I used [ : ] instead of simply true because OP used the similar [[ ... ]] in the question. – pLumo Jun 26 '20 at 12:28
  • 1
    @pLumo, 1. OP used [[ consistently in both cases and 2. OP used it in the intended way while [ : ] basically works by accident. – Jan Hudec Jun 26 '20 at 12:39
  • 1
    @JanHudec, what do you mean "by accident"? test is defined to exit with a zero status (truthy) if only gets one argument that's not the empty string. (or one plus the tailing ] in the case of [). Anyway, for the difference between if and && it doesn't really matter how that truthy condition is acquired, so I edited this to use just true in every case. Perhaps that would be less distracting? – ilkkachu Jun 26 '20 at 12:57
  • 2
    @ilkkachu, yes, the edit is good. What I mean with “by accident” is that the way it actually works is unlikely what author had in mind when they wrote it. – Jan Hudec Jun 26 '20 at 13:04