Confusing use of && and || operators

444,878

Solution 1

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.

Solution 2

Here's my cheat sheet:

  • "A ; B" Run A and then B, regardless of success of A
  • "A && B" Run B if A succeeded
  • "A || B" Run B if A failed
  • "A &" Run A in background.

Solution 3

to expand on @Shawn-j-Goff's answer from above, && is a logical AND, and || is a logical OR.

See this part of the Advanced Bash Scripting Guide. Some of the contents from the link for user reference as below.

&& AND

if [ $condition1 ] && [ $condition2 ]
#  Same as:  if [ $condition1 -a $condition2 ]
#  Returns true if both condition1 and condition2 hold true...

if [[ $condition1 && $condition2 ]]    # Also works.
#  Note that && operator not permitted inside brackets
#+ of [ ... ] construct.

|| OR

if [ $condition1 ] || [ $condition2 ]
# Same as:  if [ $condition1 -o $condition2 ]
# Returns true if either condition1 or condition2 holds true...

if [[ $condition1 || $condition2 ]]    # Also works.
#  Note that || operator not permitted inside brackets
#+ of a [ ... ] construct.

Solution 4

From my experience I use the && and || to reduce an if statement to a single line.

Say we are looking for a file called /root/Sample.txt then the traditional iteration would be as follows in shell:

if [ -f /root/Sample.txt ]
then
    echo "file found"
else
    echo "file not found"
fi

These 6 lines can be reduced to a single line:

[[ -f /root/Sample.txt ]] && echo "file found" || echo "file not found"

When running a few iterations to set variables or to create files etc., life is easier and the script looks slicker using the single line if function, it's only drawback is that it becomes a bit more difficult to implement multiple commands from a single iteration however you can make use of functions.

Solution 5

There is a notion of "short cutting".

When (expr1 && expr2) is evaluated - expr2 is only evaluated if exp1 evaluates to "true". This is because both expr1 AND expr2 have to be true for (expr1 && expr2) to be true. If expr1 evaluates to "false" expr2 is NOT evalued (short cut) because (expr1 && expr2) is already "flase".

Try the following - assume file F1 exists & file F2 does not exist:

( [ -s F1 ] && echo "File Exists" )  # will print "File Exists" - no short cut
( [ -s F2 ] && echo "File Exists" )  # will NOT print "File Exists" - short cut

Similarly for || (or) - but short cutting is reversed.

Share:
444,878

Related videos on Youtube

user1204106
Author by

user1204106

Updated on September 18, 2022

Comments

  • user1204106
    user1204106 almost 2 years

    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?

  • ChrisCornwall
    ChrisCornwall over 12 years
    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.
  • Angel Todorov
    Angel Todorov over 12 years
    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"
  • countermode
    countermode over 7 years
    You are aware that for shells zero exit code evaluates to true and thus nonzero exit code on the left side of && results in the whole expression to return false?
  • techraf
    techraf over 7 years
    Someone did not approve your edits because it was not your answer. If you think that some answer is incorrect you should downvote it and possibly leave a comment; if you think that it requires a change, you should leave a comment. Editing is for correcting grammar, formatting, and spelling mistakes that do not change the meaning of the answer.
  • Try2Help
    Try2Help over 7 years
    @countermode I'm sorry, you are right, I thought in Linux zero = false and nonzero = true (like in C and many other languages/environments/platforms). I apologize for the misunderstanding.
  • Mr. Lance E Sloan
    Mr. Lance E Sloan over 7 years
    Not only can you "consider [ ... ] to be a program", in many cases it is. It's commonly in the file /bin/[ or /usr/bin/[.
  • Mr. Lance E Sloan
    Mr. Lance E Sloan over 7 years
    The logic is usually referred to as "short circuiting". I've never seen the phrase "short cutting" used. I mention this to help with finding references.
  • Dmitry
    Dmitry almost 7 years
    There's some interesting lambda calculus parallels going on here demonstrated in working JavaScript(define the variables in order); "left(aka true)": (a => b => a). "right(aka false)": (a => b => b). "A; B" "then" (a => b => (() => b())(a())). "A && B" "if without else(when)" (a => b => a()(() => right)(b)). "A || B" "else without if(unless)" (a => b => a()(b)(() => right)). "a && b || c" "ifThenElse" (a => b => c => (unless(when(a)(b))(c))()).
  • Dmitry
    Dmitry almost 7 years
    note that in bash, left is analogous 0/empty string, right analogous is everything else.
  • Dionysian
    Dionysian almost 7 years
    C programmers will find this super confusing. There 0 means false... While in shellscripting 0 means true... Mind blown.
  • GeneCode
    GeneCode almost 7 years
    This is cool. Reminds me of objc code (a==b)?val=1:val=2;
  • Admin
    Admin over 6 years
    Another one that you could mention is test instead of if or [. And if [ and if test seem to be interspersed with [ and test with no apparent rhyme or reason. test shows up on occasion, like at config.site for vendor libs on Fedora x86_64.
  • Katie
    Katie over 6 years
    How can i use this command when I want to run a process in the background with "&"? I get a syntax error for ./someScript.sh & && echo 'ok' || echo 'ko'
  • TimD1
    TimD1 almost 5 years
    @Calmarius If you're used to C, think of return statuses, not booleans, where return 0 means success.
  • matvore
    matvore over 4 years
    In the form: foo && bar || baz, if foo succeeds then bar fails, baz will be run, so it is subtly different from an if statement.
  • dashesy
    dashesy about 4 years
    yeah thinking of it as success/unsuccessful is certainly helping rather than 0/1 return code value.
  • Deoxal
    Deoxal over 3 years
    What about a single vertical bar?
  • s3n0
    s3n0 over 3 years
    I must note that it is possible to execute several commands in a row in {} parentheses, using && or ||, such as: pidof udpxy > /dev/null 2>&1 && echo "udpxy is up!" || { echo "udpxy is down!"; /etc/init.d/udpxy restart; }. It is also worth mentioning that if..then..else is a more reliable "recognizer" of true/false conditions than using && and ||.