Confusing use of && and || operators

  • I was skimming through an /etc/rc.d/init.d/sendmail file (I know this is hardly ever used, but I'm studying for an exam), and I've become a bit confused about the && and the || operators. I've read where they can be used in statements such as:

    if [ test1 ] && [ test2 ]; then
         echo "both tests are true"
    elif [ test1 ] || [ test2 ]; then
         echo "one test is true"
    fi
    

    However, this script shows single line statements such as:

    [ -z "$SMQUEUE" ] && SMQUEUE="QUEUE"
    [ -f /usr/sbin/sendmail ] || exit 0
    

    These seem to be using the && and || operators to elicit responses based on tests, but I haven't been able to dig up documenation regarding this particular use of these operators. Can anyone explain what these do in this particular context?

  • The right side of && will only be evaluated if the exit status of the left side is zero (i.e. true). || is the opposite: it will evaluate the right side only if the left side exit status is non-zero (i.e. false).

    You can consider [ ... ] to be a program with a return value. If the test inside evaluates to true, it returns zero; it returns nonzero otherwise.

    Examples:

    $ false && echo howdy!
    
    $ true && echo howdy!
    howdy!
    $ true || echo howdy!
    
    $ false || echo howdy!
    howdy!
    

    Extra notes:

    If you do which [, you might see that [ actually does point to a program! It's usually not actually the one that runs in scripts, though; run type [ to see what actually gets run. If you wan to try using the program, just give the full path like so: /bin/[ 1 = 1.

    When you see "X or Y", you test X. If it's true, you already know the answer to "X or Y" (it's true), so no need to test Y. If it's true, you don't know the answer to "X or Y", so you do need to test Y. When you see "X and Y", you test X. If it's false, you already know the answer to "X and Y" (it's false), so no need to test Y. If X is true, then you do need to test Y to see if "X and Y" is true.

    Instead of "if the left side returns zero", I would write "if the left side command's exit status is zero". I find "return" a bit ambiguous as the output and the exit status can both be considered as "return values"

    Not only can you "_consider_ `[ ... ]` to be a program", in many cases it **_is_**. It's commonly in the file `/bin/[` or `/usr/bin/[`.

    C programmers will find this super confusing. There 0 means false... While in shellscripting 0 means true... Mind blown.

    @Calmarius If you're used to C, think of `return` statuses, not booleans, where `return 0` means success.

    yeah thinking of it as success/unsuccessful is certainly helping rather than 0/1 return code value.

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM