0

What is the difference between the if [[ ... ]] ; then ... and the [[ ... ]] && ... constructs in Bash, other than syntax? For example:

if [[ -d /etc ]] ; then echo "I see." ; else echo "I don't." ; fi
[[ -d /etc ]] && echo "I see." || echo "I don't."

What can one do that the other cannot?

  • 3
    It's [BashPitfall #22](https://mywiki.wooledge.org/BashPitfalls#cmd1_.26.26_cmd2_.7C.7C_cmd3). – Benjamin W. Jan 02 '19 at 14:59
  • ...see also [Ternary operator in bash?](https://stackoverflow.com/questions/3953645/ternary-operator-in-bash), especially the comment https://stackoverflow.com/questions/3953645/ternary-operator-in-bash#comment73915813_3953666 and [the answer by Ivan Pozdeev](https://stackoverflow.com/a/25119904/14122). – Charles Duffy Jan 02 '19 at 15:02

2 Answers2

3

There are not many differences, but one is that the first example is only using the first condition. In the second there are two conditions that effect the output.

if [[ -d /etc ]] ; # only condition that matters
 then echo "I see." ;
 else echo "I don't." ; 
fi

[[ -d /etc ]] &&  # condition 1
echo "I see." || # condition 2
echo "I don't."

In this example condtion 2 will always be fine, as echo is a builtin function, but if it was another command, and it failed it would trigger the or clause, which is not possible in the first example. The first one only uses one condition the second relies on two conditions.

Nick Ellis
  • 1,048
  • 11
  • 24
  • 2
    Technically, `echo` can fail (for instance, if its standard output is redirected to a read-only file); it's just isn't common. – chepner Jan 02 '19 at 14:38
0

Addendum - It is a relevant aside that you can put multiple statements in each block of a properly formatted if/then/elif/else without much special effort (though it does take some finagling on the if part) but the ternary construct requires that you create blocks yourself.

if true && false || oops
then : "this shan't be executed"
     : but I can put several statements anyway
elif true && true || oops
then echo hello
     echo more statements!
else : I could put more statements here too
     : see?
fi
bash: oops: command not found
hello
more statements!

To create multiple-statements blocks in a ternary you need something like this -

true && {
   echo ok
   echo more
   oops!
} || false {
   echo This still has the same logical vulnerability, now made *worse*
   echo oh, woe.
}
ok
more
bash: oops!: command not found
       echo This still has the same logical vulnerability
This still has the same logical vulnerability
       echo oh, woe.
oh, woe.
    }
bash: syntax error near unexpected token `}'

It could be cleaned up a bit, but that isn't the point.
They aren't the same.

Paul Hodges
  • 13,382
  • 1
  • 17
  • 36