Understanding boolean operators in bash script [duplicate]












13
















This question already has an answer here:




  • Invert boolean variable

    5 answers




phone_missing=false
echo "missing $phone_missing"

if [ ! $phone_missing ]
then
echo "Lost phone at $readabletime"
$phone_missing=true
fi


I just can't understand this.
The line



echo "missing $phone_missing"


echos missing false, I would expect the statement



if [ ! $phone_missing ]


to be true and enter the if clause, but it doesn't? What am I missing here!?










share|improve this question















marked as duplicate by Rui F Ribeiro, mosvy, Kusalananda bash
Users with the  bash badge can single-handedly close bash questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
5 hours ago


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.























    13
















    This question already has an answer here:




    • Invert boolean variable

      5 answers




    phone_missing=false
    echo "missing $phone_missing"

    if [ ! $phone_missing ]
    then
    echo "Lost phone at $readabletime"
    $phone_missing=true
    fi


    I just can't understand this.
    The line



    echo "missing $phone_missing"


    echos missing false, I would expect the statement



    if [ ! $phone_missing ]


    to be true and enter the if clause, but it doesn't? What am I missing here!?










    share|improve this question















    marked as duplicate by Rui F Ribeiro, mosvy, Kusalananda bash
    Users with the  bash badge can single-handedly close bash questions as duplicates and reopen them as needed.

    StackExchange.ready(function() {
    if (StackExchange.options.isMobile) return;

    $('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
    var $hover = $(this).addClass('hover-bound'),
    $msg = $hover.siblings('.dupe-hammer-message');

    $hover.hover(
    function() {
    $hover.showInfoMessage('', {
    messageElement: $msg.clone().show(),
    transient: false,
    position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
    dismissable: false,
    relativeToBody: true
    });
    },
    function() {
    StackExchange.helpers.removeMessages();
    }
    );
    });
    });
    5 hours ago


    This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.





















      13












      13








      13


      6







      This question already has an answer here:




      • Invert boolean variable

        5 answers




      phone_missing=false
      echo "missing $phone_missing"

      if [ ! $phone_missing ]
      then
      echo "Lost phone at $readabletime"
      $phone_missing=true
      fi


      I just can't understand this.
      The line



      echo "missing $phone_missing"


      echos missing false, I would expect the statement



      if [ ! $phone_missing ]


      to be true and enter the if clause, but it doesn't? What am I missing here!?










      share|improve this question

















      This question already has an answer here:




      • Invert boolean variable

        5 answers




      phone_missing=false
      echo "missing $phone_missing"

      if [ ! $phone_missing ]
      then
      echo "Lost phone at $readabletime"
      $phone_missing=true
      fi


      I just can't understand this.
      The line



      echo "missing $phone_missing"


      echos missing false, I would expect the statement



      if [ ! $phone_missing ]


      to be true and enter the if clause, but it doesn't? What am I missing here!?





      This question already has an answer here:




      • Invert boolean variable

        5 answers








      bash scripting






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 10 hours ago









      Rui F Ribeiro

      41.3k1481140




      41.3k1481140










      asked Dec 19 '13 at 18:31









      ascoasco

      182116




      182116




      marked as duplicate by Rui F Ribeiro, mosvy, Kusalananda bash
      Users with the  bash badge can single-handedly close bash questions as duplicates and reopen them as needed.

      StackExchange.ready(function() {
      if (StackExchange.options.isMobile) return;

      $('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
      var $hover = $(this).addClass('hover-bound'),
      $msg = $hover.siblings('.dupe-hammer-message');

      $hover.hover(
      function() {
      $hover.showInfoMessage('', {
      messageElement: $msg.clone().show(),
      transient: false,
      position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
      dismissable: false,
      relativeToBody: true
      });
      },
      function() {
      StackExchange.helpers.removeMessages();
      }
      );
      });
      });
      5 hours ago


      This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.









      marked as duplicate by Rui F Ribeiro, mosvy, Kusalananda bash
      Users with the  bash badge can single-handedly close bash questions as duplicates and reopen them as needed.

      StackExchange.ready(function() {
      if (StackExchange.options.isMobile) return;

      $('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
      var $hover = $(this).addClass('hover-bound'),
      $msg = $hover.siblings('.dupe-hammer-message');

      $hover.hover(
      function() {
      $hover.showInfoMessage('', {
      messageElement: $msg.clone().show(),
      transient: false,
      position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
      dismissable: false,
      relativeToBody: true
      });
      },
      function() {
      StackExchange.helpers.removeMessages();
      }
      );
      });
      });
      5 hours ago


      This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
























          7 Answers
          7






          active

          oldest

          votes


















          12














          $phone_missing is a string that happens to contain "false". And a non-empty string evaluates to true. See also http://www.linuxintro.org/wiki/Babe#empty_strings






          share|improve this answer


























          • Ah alright. I would have declared that variable as boolean (at least not with the declare word) but the ash console won't let me. I also don't want to compare Strings. How is this done right?

            – asco
            Dec 19 '13 at 18:57






          • 1





            stackoverflow.com/questions/2953646/…, but take care: this guy EXECUTES a string variable, and as well false as true are unix commands.

            – Thorsten Staerk
            Dec 19 '13 at 19:01





















          11














          I often use "true" and "false" since they are also commands that merely return success and failure respectively. Then you can do



          if "$phone_missing"; then ...





          share|improve this answer

































            5














            Here's one way to do this, while retaining the true/false values.



            phone_missing=false
            if [ "$phone_missing" != false ]; then
            echo "phone_missing is not 'false' (but may be non-true, too)"
            fi
            if [ "$phone_missing" == true ]; then
            echo "phone_missing is true."
            fi


            The double quotes around $phone_missing are to protect against the case where variable phone_missing is not defined at all. Another common idiom to ward against this is [ x$phone_missing != xfalse ], but the quotes seem more natural to me.



            The hint is in the bash help page for test:




              STRING      True if string is not empty.
            ...
            ! EXPR True if expr is false.



            So, basically [ $foo ] will be true if $foo is non-empty. Not true or false, just non-empty. [ ! $foo ] is true if $foo is empty or undefined.



            You could always change your code to just set phone_missing to a non-empty value, which will denote true. If phone_missing is unset (or empty — phone_missing=""), it will be false. Otherwise, you should be using the string testing operators (= and !=).



            The other slight issue is the assignment. You have it as $phone_missing=true, whereas it should be phone_missing=true (no dollar sign).



            Sorry if this is a bit dense, it's because I am. It's been a long day. :)






            share|improve this answer

































              0














              I would have done this as a comment to support James Ko but didn't have the rep to comment or publicly up vote.



              The issue here is that the brackets are notation for doing a comparison test such as value or string equality.



              String truthiness in bash for an empty string is "" (empty string) evaluates to false (return value 1) and any non empty string "false" "true" or "bob's your uncle" evaluates to true (return value 0).



              You can prove this to yourself with:



                  if [ "foo" ]; then 
              echo true is $?;
              else
              echo false is $?;
              fi


              The $?above is a special variable that holds the last commands exit status (0 success, and any > 0 for error code) and will output true is 0. You can replace "foo" with anything you want and the result will be the same except if you replace it with an empty string "" or '' in which case it will evaluate the else condition and output false is 1.



              When using the brackets the internal statement such as ! $phone_missing is evaluated and then returns a 0 for true or 1 for false to the if control statement. Since the bracket evaluates string and value comparisons the $phone_missing is first expanded to the non empty string "false" which is evaluated by the as non empty string (or true) and then the ! inverts the result which results in the if statement getting a false (or return value 1) and it skips the conditional body executing the else statement if present.



              As James Ko said the notation would be to just pass the variable holding your 'boolean' to the if control statement. Note that in bash a boolean true and false must be lower case as in:
              bool_true=true
              bool_false=false
              Any other case will evaluate as strings and not boolean.



              So using your example and James Ko's answer it would be:



              phone_missing=false
              echo "missing $phone_missing"

              if ! $phone_missing
              then
              echo "Lost phone at $readabletime"
              $phone_missing=true
              fi


              or as I prefer for readability (syntactically the same and James Ko's)



              phone_missing=false
              echo "missing $phone_missing"

              if ( ! $phone_missing ); then
              echo "Lost phone at $readabletime"
              $phone_missing=true
              fi


              Other answers such as by Alexios are literally checking the string content. So that either of the following would result in false:



              phone_missing=false
              if [ "$phone_missing" != false ]; then
              echo "phone_missing is not 'false' (but may be non-true, too)"
              fi
              if [ "$phone_missing" == true ]; then
              echo "phone_missing is not 'false' (but may be non-true, too)"
              fi
              if [ "$phone_missing" == Bobs_your_uncle ]; then
              echo "phone_missing is not 'false' (but may be non-true, too)"
              fi





              share|improve this answer































                0














                Other answers gave you solution, but I will explain what was wrong with the original thinking.



                Bash variables don't have types, so there's no such thing as a boolean variable or value like true or false. Basically all bash variables are just strings.



                When you test a variable/string in bash without specifying the type of test (-n or -z), it will default to a -n (nonzero length string) test.



                So [ "$var" ] is equivalent to [ -n "$var" ]. As long as $var contains at least 1 character, it was evaluate to true.



                Since you negated the expression, [ ! "$var" ] is equivalent to [ ! -n "$var" ]. So if $var contains at least 1 character, then the expression is false.



                Since false (which is just a string) contains 5 characters, the expression is false. If doesn't matter what string you set phone_missing to (true, 0, 1), the expression will always be false because is phone_missing is nonzero length. The only way to make it true is phone_missing="" since that is zero length.






                share|improve this answer































                  0














                  Don't use string for boolean. Use integer.



                  Input:



                  val=1
                  ((val)) && echo "true" || echo "false"
                  val=0
                  ((val)) && echo "true" || echo "false"


                  Output:



                  true
                  false


                  Source:




                  ((expression))



                  The expression is evaluated according to the rules described below under ARITHMETIC EVALUATION. If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1. This is exactly equivalent to let "expression".







                  share|improve this answer































                    -1














                    The correct syntax is if ! $bool; then [statements]; fi.



                    Example:



                    bool=false

                    if ! $bool; then
                    echo "This is correct!"
                    fi

                    if [ ! $bool ]; then
                    echo "This is wrong!"
                    fi


                    Output: This is correct!






                    share|improve this answer
























                    • There’s a kernel of truth in your answer, but, lacking any explanation, it causes more confusion than it remedies.  Also, it is little more than a repeat of one of the previous answers.  If you don’t want your answer to be removed, explain why it is right.

                      – G-Man
                      May 24 '15 at 6:17


















                    7 Answers
                    7






                    active

                    oldest

                    votes








                    7 Answers
                    7






                    active

                    oldest

                    votes









                    active

                    oldest

                    votes






                    active

                    oldest

                    votes









                    12














                    $phone_missing is a string that happens to contain "false". And a non-empty string evaluates to true. See also http://www.linuxintro.org/wiki/Babe#empty_strings






                    share|improve this answer


























                    • Ah alright. I would have declared that variable as boolean (at least not with the declare word) but the ash console won't let me. I also don't want to compare Strings. How is this done right?

                      – asco
                      Dec 19 '13 at 18:57






                    • 1





                      stackoverflow.com/questions/2953646/…, but take care: this guy EXECUTES a string variable, and as well false as true are unix commands.

                      – Thorsten Staerk
                      Dec 19 '13 at 19:01


















                    12














                    $phone_missing is a string that happens to contain "false". And a non-empty string evaluates to true. See also http://www.linuxintro.org/wiki/Babe#empty_strings






                    share|improve this answer


























                    • Ah alright. I would have declared that variable as boolean (at least not with the declare word) but the ash console won't let me. I also don't want to compare Strings. How is this done right?

                      – asco
                      Dec 19 '13 at 18:57






                    • 1





                      stackoverflow.com/questions/2953646/…, but take care: this guy EXECUTES a string variable, and as well false as true are unix commands.

                      – Thorsten Staerk
                      Dec 19 '13 at 19:01
















                    12












                    12








                    12







                    $phone_missing is a string that happens to contain "false". And a non-empty string evaluates to true. See also http://www.linuxintro.org/wiki/Babe#empty_strings






                    share|improve this answer















                    $phone_missing is a string that happens to contain "false". And a non-empty string evaluates to true. See also http://www.linuxintro.org/wiki/Babe#empty_strings







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited May 24 '15 at 7:35

























                    answered Dec 19 '13 at 18:46









                    Thorsten StaerkThorsten Staerk

                    2,26411323




                    2,26411323













                    • Ah alright. I would have declared that variable as boolean (at least not with the declare word) but the ash console won't let me. I also don't want to compare Strings. How is this done right?

                      – asco
                      Dec 19 '13 at 18:57






                    • 1





                      stackoverflow.com/questions/2953646/…, but take care: this guy EXECUTES a string variable, and as well false as true are unix commands.

                      – Thorsten Staerk
                      Dec 19 '13 at 19:01





















                    • Ah alright. I would have declared that variable as boolean (at least not with the declare word) but the ash console won't let me. I also don't want to compare Strings. How is this done right?

                      – asco
                      Dec 19 '13 at 18:57






                    • 1





                      stackoverflow.com/questions/2953646/…, but take care: this guy EXECUTES a string variable, and as well false as true are unix commands.

                      – Thorsten Staerk
                      Dec 19 '13 at 19:01



















                    Ah alright. I would have declared that variable as boolean (at least not with the declare word) but the ash console won't let me. I also don't want to compare Strings. How is this done right?

                    – asco
                    Dec 19 '13 at 18:57





                    Ah alright. I would have declared that variable as boolean (at least not with the declare word) but the ash console won't let me. I also don't want to compare Strings. How is this done right?

                    – asco
                    Dec 19 '13 at 18:57




                    1




                    1





                    stackoverflow.com/questions/2953646/…, but take care: this guy EXECUTES a string variable, and as well false as true are unix commands.

                    – Thorsten Staerk
                    Dec 19 '13 at 19:01







                    stackoverflow.com/questions/2953646/…, but take care: this guy EXECUTES a string variable, and as well false as true are unix commands.

                    – Thorsten Staerk
                    Dec 19 '13 at 19:01















                    11














                    I often use "true" and "false" since they are also commands that merely return success and failure respectively. Then you can do



                    if "$phone_missing"; then ...





                    share|improve this answer






























                      11














                      I often use "true" and "false" since they are also commands that merely return success and failure respectively. Then you can do



                      if "$phone_missing"; then ...





                      share|improve this answer




























                        11












                        11








                        11







                        I often use "true" and "false" since they are also commands that merely return success and failure respectively. Then you can do



                        if "$phone_missing"; then ...





                        share|improve this answer















                        I often use "true" and "false" since they are also commands that merely return success and failure respectively. Then you can do



                        if "$phone_missing"; then ...






                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Dec 20 '13 at 0:26









                        Stéphane Chazelas

                        309k57582942




                        309k57582942










                        answered Dec 19 '13 at 18:58









                        glenn jackmanglenn jackman

                        52.2k572112




                        52.2k572112























                            5














                            Here's one way to do this, while retaining the true/false values.



                            phone_missing=false
                            if [ "$phone_missing" != false ]; then
                            echo "phone_missing is not 'false' (but may be non-true, too)"
                            fi
                            if [ "$phone_missing" == true ]; then
                            echo "phone_missing is true."
                            fi


                            The double quotes around $phone_missing are to protect against the case where variable phone_missing is not defined at all. Another common idiom to ward against this is [ x$phone_missing != xfalse ], but the quotes seem more natural to me.



                            The hint is in the bash help page for test:




                              STRING      True if string is not empty.
                            ...
                            ! EXPR True if expr is false.



                            So, basically [ $foo ] will be true if $foo is non-empty. Not true or false, just non-empty. [ ! $foo ] is true if $foo is empty or undefined.



                            You could always change your code to just set phone_missing to a non-empty value, which will denote true. If phone_missing is unset (or empty — phone_missing=""), it will be false. Otherwise, you should be using the string testing operators (= and !=).



                            The other slight issue is the assignment. You have it as $phone_missing=true, whereas it should be phone_missing=true (no dollar sign).



                            Sorry if this is a bit dense, it's because I am. It's been a long day. :)






                            share|improve this answer






























                              5














                              Here's one way to do this, while retaining the true/false values.



                              phone_missing=false
                              if [ "$phone_missing" != false ]; then
                              echo "phone_missing is not 'false' (but may be non-true, too)"
                              fi
                              if [ "$phone_missing" == true ]; then
                              echo "phone_missing is true."
                              fi


                              The double quotes around $phone_missing are to protect against the case where variable phone_missing is not defined at all. Another common idiom to ward against this is [ x$phone_missing != xfalse ], but the quotes seem more natural to me.



                              The hint is in the bash help page for test:




                                STRING      True if string is not empty.
                              ...
                              ! EXPR True if expr is false.



                              So, basically [ $foo ] will be true if $foo is non-empty. Not true or false, just non-empty. [ ! $foo ] is true if $foo is empty or undefined.



                              You could always change your code to just set phone_missing to a non-empty value, which will denote true. If phone_missing is unset (or empty — phone_missing=""), it will be false. Otherwise, you should be using the string testing operators (= and !=).



                              The other slight issue is the assignment. You have it as $phone_missing=true, whereas it should be phone_missing=true (no dollar sign).



                              Sorry if this is a bit dense, it's because I am. It's been a long day. :)






                              share|improve this answer




























                                5












                                5








                                5







                                Here's one way to do this, while retaining the true/false values.



                                phone_missing=false
                                if [ "$phone_missing" != false ]; then
                                echo "phone_missing is not 'false' (but may be non-true, too)"
                                fi
                                if [ "$phone_missing" == true ]; then
                                echo "phone_missing is true."
                                fi


                                The double quotes around $phone_missing are to protect against the case where variable phone_missing is not defined at all. Another common idiom to ward against this is [ x$phone_missing != xfalse ], but the quotes seem more natural to me.



                                The hint is in the bash help page for test:




                                  STRING      True if string is not empty.
                                ...
                                ! EXPR True if expr is false.



                                So, basically [ $foo ] will be true if $foo is non-empty. Not true or false, just non-empty. [ ! $foo ] is true if $foo is empty or undefined.



                                You could always change your code to just set phone_missing to a non-empty value, which will denote true. If phone_missing is unset (or empty — phone_missing=""), it will be false. Otherwise, you should be using the string testing operators (= and !=).



                                The other slight issue is the assignment. You have it as $phone_missing=true, whereas it should be phone_missing=true (no dollar sign).



                                Sorry if this is a bit dense, it's because I am. It's been a long day. :)






                                share|improve this answer















                                Here's one way to do this, while retaining the true/false values.



                                phone_missing=false
                                if [ "$phone_missing" != false ]; then
                                echo "phone_missing is not 'false' (but may be non-true, too)"
                                fi
                                if [ "$phone_missing" == true ]; then
                                echo "phone_missing is true."
                                fi


                                The double quotes around $phone_missing are to protect against the case where variable phone_missing is not defined at all. Another common idiom to ward against this is [ x$phone_missing != xfalse ], but the quotes seem more natural to me.



                                The hint is in the bash help page for test:




                                  STRING      True if string is not empty.
                                ...
                                ! EXPR True if expr is false.



                                So, basically [ $foo ] will be true if $foo is non-empty. Not true or false, just non-empty. [ ! $foo ] is true if $foo is empty or undefined.



                                You could always change your code to just set phone_missing to a non-empty value, which will denote true. If phone_missing is unset (or empty — phone_missing=""), it will be false. Otherwise, you should be using the string testing operators (= and !=).



                                The other slight issue is the assignment. You have it as $phone_missing=true, whereas it should be phone_missing=true (no dollar sign).



                                Sorry if this is a bit dense, it's because I am. It's been a long day. :)







                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited Nov 7 '14 at 17:31









                                Ramesh

                                23.8k34104186




                                23.8k34104186










                                answered Dec 19 '13 at 20:54









                                AlexiosAlexios

                                14.5k14966




                                14.5k14966























                                    0














                                    I would have done this as a comment to support James Ko but didn't have the rep to comment or publicly up vote.



                                    The issue here is that the brackets are notation for doing a comparison test such as value or string equality.



                                    String truthiness in bash for an empty string is "" (empty string) evaluates to false (return value 1) and any non empty string "false" "true" or "bob's your uncle" evaluates to true (return value 0).



                                    You can prove this to yourself with:



                                        if [ "foo" ]; then 
                                    echo true is $?;
                                    else
                                    echo false is $?;
                                    fi


                                    The $?above is a special variable that holds the last commands exit status (0 success, and any > 0 for error code) and will output true is 0. You can replace "foo" with anything you want and the result will be the same except if you replace it with an empty string "" or '' in which case it will evaluate the else condition and output false is 1.



                                    When using the brackets the internal statement such as ! $phone_missing is evaluated and then returns a 0 for true or 1 for false to the if control statement. Since the bracket evaluates string and value comparisons the $phone_missing is first expanded to the non empty string "false" which is evaluated by the as non empty string (or true) and then the ! inverts the result which results in the if statement getting a false (or return value 1) and it skips the conditional body executing the else statement if present.



                                    As James Ko said the notation would be to just pass the variable holding your 'boolean' to the if control statement. Note that in bash a boolean true and false must be lower case as in:
                                    bool_true=true
                                    bool_false=false
                                    Any other case will evaluate as strings and not boolean.



                                    So using your example and James Ko's answer it would be:



                                    phone_missing=false
                                    echo "missing $phone_missing"

                                    if ! $phone_missing
                                    then
                                    echo "Lost phone at $readabletime"
                                    $phone_missing=true
                                    fi


                                    or as I prefer for readability (syntactically the same and James Ko's)



                                    phone_missing=false
                                    echo "missing $phone_missing"

                                    if ( ! $phone_missing ); then
                                    echo "Lost phone at $readabletime"
                                    $phone_missing=true
                                    fi


                                    Other answers such as by Alexios are literally checking the string content. So that either of the following would result in false:



                                    phone_missing=false
                                    if [ "$phone_missing" != false ]; then
                                    echo "phone_missing is not 'false' (but may be non-true, too)"
                                    fi
                                    if [ "$phone_missing" == true ]; then
                                    echo "phone_missing is not 'false' (but may be non-true, too)"
                                    fi
                                    if [ "$phone_missing" == Bobs_your_uncle ]; then
                                    echo "phone_missing is not 'false' (but may be non-true, too)"
                                    fi





                                    share|improve this answer




























                                      0














                                      I would have done this as a comment to support James Ko but didn't have the rep to comment or publicly up vote.



                                      The issue here is that the brackets are notation for doing a comparison test such as value or string equality.



                                      String truthiness in bash for an empty string is "" (empty string) evaluates to false (return value 1) and any non empty string "false" "true" or "bob's your uncle" evaluates to true (return value 0).



                                      You can prove this to yourself with:



                                          if [ "foo" ]; then 
                                      echo true is $?;
                                      else
                                      echo false is $?;
                                      fi


                                      The $?above is a special variable that holds the last commands exit status (0 success, and any > 0 for error code) and will output true is 0. You can replace "foo" with anything you want and the result will be the same except if you replace it with an empty string "" or '' in which case it will evaluate the else condition and output false is 1.



                                      When using the brackets the internal statement such as ! $phone_missing is evaluated and then returns a 0 for true or 1 for false to the if control statement. Since the bracket evaluates string and value comparisons the $phone_missing is first expanded to the non empty string "false" which is evaluated by the as non empty string (or true) and then the ! inverts the result which results in the if statement getting a false (or return value 1) and it skips the conditional body executing the else statement if present.



                                      As James Ko said the notation would be to just pass the variable holding your 'boolean' to the if control statement. Note that in bash a boolean true and false must be lower case as in:
                                      bool_true=true
                                      bool_false=false
                                      Any other case will evaluate as strings and not boolean.



                                      So using your example and James Ko's answer it would be:



                                      phone_missing=false
                                      echo "missing $phone_missing"

                                      if ! $phone_missing
                                      then
                                      echo "Lost phone at $readabletime"
                                      $phone_missing=true
                                      fi


                                      or as I prefer for readability (syntactically the same and James Ko's)



                                      phone_missing=false
                                      echo "missing $phone_missing"

                                      if ( ! $phone_missing ); then
                                      echo "Lost phone at $readabletime"
                                      $phone_missing=true
                                      fi


                                      Other answers such as by Alexios are literally checking the string content. So that either of the following would result in false:



                                      phone_missing=false
                                      if [ "$phone_missing" != false ]; then
                                      echo "phone_missing is not 'false' (but may be non-true, too)"
                                      fi
                                      if [ "$phone_missing" == true ]; then
                                      echo "phone_missing is not 'false' (but may be non-true, too)"
                                      fi
                                      if [ "$phone_missing" == Bobs_your_uncle ]; then
                                      echo "phone_missing is not 'false' (but may be non-true, too)"
                                      fi





                                      share|improve this answer


























                                        0












                                        0








                                        0







                                        I would have done this as a comment to support James Ko but didn't have the rep to comment or publicly up vote.



                                        The issue here is that the brackets are notation for doing a comparison test such as value or string equality.



                                        String truthiness in bash for an empty string is "" (empty string) evaluates to false (return value 1) and any non empty string "false" "true" or "bob's your uncle" evaluates to true (return value 0).



                                        You can prove this to yourself with:



                                            if [ "foo" ]; then 
                                        echo true is $?;
                                        else
                                        echo false is $?;
                                        fi


                                        The $?above is a special variable that holds the last commands exit status (0 success, and any > 0 for error code) and will output true is 0. You can replace "foo" with anything you want and the result will be the same except if you replace it with an empty string "" or '' in which case it will evaluate the else condition and output false is 1.



                                        When using the brackets the internal statement such as ! $phone_missing is evaluated and then returns a 0 for true or 1 for false to the if control statement. Since the bracket evaluates string and value comparisons the $phone_missing is first expanded to the non empty string "false" which is evaluated by the as non empty string (or true) and then the ! inverts the result which results in the if statement getting a false (or return value 1) and it skips the conditional body executing the else statement if present.



                                        As James Ko said the notation would be to just pass the variable holding your 'boolean' to the if control statement. Note that in bash a boolean true and false must be lower case as in:
                                        bool_true=true
                                        bool_false=false
                                        Any other case will evaluate as strings and not boolean.



                                        So using your example and James Ko's answer it would be:



                                        phone_missing=false
                                        echo "missing $phone_missing"

                                        if ! $phone_missing
                                        then
                                        echo "Lost phone at $readabletime"
                                        $phone_missing=true
                                        fi


                                        or as I prefer for readability (syntactically the same and James Ko's)



                                        phone_missing=false
                                        echo "missing $phone_missing"

                                        if ( ! $phone_missing ); then
                                        echo "Lost phone at $readabletime"
                                        $phone_missing=true
                                        fi


                                        Other answers such as by Alexios are literally checking the string content. So that either of the following would result in false:



                                        phone_missing=false
                                        if [ "$phone_missing" != false ]; then
                                        echo "phone_missing is not 'false' (but may be non-true, too)"
                                        fi
                                        if [ "$phone_missing" == true ]; then
                                        echo "phone_missing is not 'false' (but may be non-true, too)"
                                        fi
                                        if [ "$phone_missing" == Bobs_your_uncle ]; then
                                        echo "phone_missing is not 'false' (but may be non-true, too)"
                                        fi





                                        share|improve this answer













                                        I would have done this as a comment to support James Ko but didn't have the rep to comment or publicly up vote.



                                        The issue here is that the brackets are notation for doing a comparison test such as value or string equality.



                                        String truthiness in bash for an empty string is "" (empty string) evaluates to false (return value 1) and any non empty string "false" "true" or "bob's your uncle" evaluates to true (return value 0).



                                        You can prove this to yourself with:



                                            if [ "foo" ]; then 
                                        echo true is $?;
                                        else
                                        echo false is $?;
                                        fi


                                        The $?above is a special variable that holds the last commands exit status (0 success, and any > 0 for error code) and will output true is 0. You can replace "foo" with anything you want and the result will be the same except if you replace it with an empty string "" or '' in which case it will evaluate the else condition and output false is 1.



                                        When using the brackets the internal statement such as ! $phone_missing is evaluated and then returns a 0 for true or 1 for false to the if control statement. Since the bracket evaluates string and value comparisons the $phone_missing is first expanded to the non empty string "false" which is evaluated by the as non empty string (or true) and then the ! inverts the result which results in the if statement getting a false (or return value 1) and it skips the conditional body executing the else statement if present.



                                        As James Ko said the notation would be to just pass the variable holding your 'boolean' to the if control statement. Note that in bash a boolean true and false must be lower case as in:
                                        bool_true=true
                                        bool_false=false
                                        Any other case will evaluate as strings and not boolean.



                                        So using your example and James Ko's answer it would be:



                                        phone_missing=false
                                        echo "missing $phone_missing"

                                        if ! $phone_missing
                                        then
                                        echo "Lost phone at $readabletime"
                                        $phone_missing=true
                                        fi


                                        or as I prefer for readability (syntactically the same and James Ko's)



                                        phone_missing=false
                                        echo "missing $phone_missing"

                                        if ( ! $phone_missing ); then
                                        echo "Lost phone at $readabletime"
                                        $phone_missing=true
                                        fi


                                        Other answers such as by Alexios are literally checking the string content. So that either of the following would result in false:



                                        phone_missing=false
                                        if [ "$phone_missing" != false ]; then
                                        echo "phone_missing is not 'false' (but may be non-true, too)"
                                        fi
                                        if [ "$phone_missing" == true ]; then
                                        echo "phone_missing is not 'false' (but may be non-true, too)"
                                        fi
                                        if [ "$phone_missing" == Bobs_your_uncle ]; then
                                        echo "phone_missing is not 'false' (but may be non-true, too)"
                                        fi






                                        share|improve this answer












                                        share|improve this answer



                                        share|improve this answer










                                        answered Sep 14 '15 at 18:26









                                        DVSDVS

                                        101




                                        101























                                            0














                                            Other answers gave you solution, but I will explain what was wrong with the original thinking.



                                            Bash variables don't have types, so there's no such thing as a boolean variable or value like true or false. Basically all bash variables are just strings.



                                            When you test a variable/string in bash without specifying the type of test (-n or -z), it will default to a -n (nonzero length string) test.



                                            So [ "$var" ] is equivalent to [ -n "$var" ]. As long as $var contains at least 1 character, it was evaluate to true.



                                            Since you negated the expression, [ ! "$var" ] is equivalent to [ ! -n "$var" ]. So if $var contains at least 1 character, then the expression is false.



                                            Since false (which is just a string) contains 5 characters, the expression is false. If doesn't matter what string you set phone_missing to (true, 0, 1), the expression will always be false because is phone_missing is nonzero length. The only way to make it true is phone_missing="" since that is zero length.






                                            share|improve this answer




























                                              0














                                              Other answers gave you solution, but I will explain what was wrong with the original thinking.



                                              Bash variables don't have types, so there's no such thing as a boolean variable or value like true or false. Basically all bash variables are just strings.



                                              When you test a variable/string in bash without specifying the type of test (-n or -z), it will default to a -n (nonzero length string) test.



                                              So [ "$var" ] is equivalent to [ -n "$var" ]. As long as $var contains at least 1 character, it was evaluate to true.



                                              Since you negated the expression, [ ! "$var" ] is equivalent to [ ! -n "$var" ]. So if $var contains at least 1 character, then the expression is false.



                                              Since false (which is just a string) contains 5 characters, the expression is false. If doesn't matter what string you set phone_missing to (true, 0, 1), the expression will always be false because is phone_missing is nonzero length. The only way to make it true is phone_missing="" since that is zero length.






                                              share|improve this answer


























                                                0












                                                0








                                                0







                                                Other answers gave you solution, but I will explain what was wrong with the original thinking.



                                                Bash variables don't have types, so there's no such thing as a boolean variable or value like true or false. Basically all bash variables are just strings.



                                                When you test a variable/string in bash without specifying the type of test (-n or -z), it will default to a -n (nonzero length string) test.



                                                So [ "$var" ] is equivalent to [ -n "$var" ]. As long as $var contains at least 1 character, it was evaluate to true.



                                                Since you negated the expression, [ ! "$var" ] is equivalent to [ ! -n "$var" ]. So if $var contains at least 1 character, then the expression is false.



                                                Since false (which is just a string) contains 5 characters, the expression is false. If doesn't matter what string you set phone_missing to (true, 0, 1), the expression will always be false because is phone_missing is nonzero length. The only way to make it true is phone_missing="" since that is zero length.






                                                share|improve this answer













                                                Other answers gave you solution, but I will explain what was wrong with the original thinking.



                                                Bash variables don't have types, so there's no such thing as a boolean variable or value like true or false. Basically all bash variables are just strings.



                                                When you test a variable/string in bash without specifying the type of test (-n or -z), it will default to a -n (nonzero length string) test.



                                                So [ "$var" ] is equivalent to [ -n "$var" ]. As long as $var contains at least 1 character, it was evaluate to true.



                                                Since you negated the expression, [ ! "$var" ] is equivalent to [ ! -n "$var" ]. So if $var contains at least 1 character, then the expression is false.



                                                Since false (which is just a string) contains 5 characters, the expression is false. If doesn't matter what string you set phone_missing to (true, 0, 1), the expression will always be false because is phone_missing is nonzero length. The only way to make it true is phone_missing="" since that is zero length.







                                                share|improve this answer












                                                share|improve this answer



                                                share|improve this answer










                                                answered Jun 1 '18 at 3:47









                                                wisbuckywisbucky

                                                678810




                                                678810























                                                    0














                                                    Don't use string for boolean. Use integer.



                                                    Input:



                                                    val=1
                                                    ((val)) && echo "true" || echo "false"
                                                    val=0
                                                    ((val)) && echo "true" || echo "false"


                                                    Output:



                                                    true
                                                    false


                                                    Source:




                                                    ((expression))



                                                    The expression is evaluated according to the rules described below under ARITHMETIC EVALUATION. If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1. This is exactly equivalent to let "expression".







                                                    share|improve this answer




























                                                      0














                                                      Don't use string for boolean. Use integer.



                                                      Input:



                                                      val=1
                                                      ((val)) && echo "true" || echo "false"
                                                      val=0
                                                      ((val)) && echo "true" || echo "false"


                                                      Output:



                                                      true
                                                      false


                                                      Source:




                                                      ((expression))



                                                      The expression is evaluated according to the rules described below under ARITHMETIC EVALUATION. If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1. This is exactly equivalent to let "expression".







                                                      share|improve this answer


























                                                        0












                                                        0








                                                        0







                                                        Don't use string for boolean. Use integer.



                                                        Input:



                                                        val=1
                                                        ((val)) && echo "true" || echo "false"
                                                        val=0
                                                        ((val)) && echo "true" || echo "false"


                                                        Output:



                                                        true
                                                        false


                                                        Source:




                                                        ((expression))



                                                        The expression is evaluated according to the rules described below under ARITHMETIC EVALUATION. If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1. This is exactly equivalent to let "expression".







                                                        share|improve this answer













                                                        Don't use string for boolean. Use integer.



                                                        Input:



                                                        val=1
                                                        ((val)) && echo "true" || echo "false"
                                                        val=0
                                                        ((val)) && echo "true" || echo "false"


                                                        Output:



                                                        true
                                                        false


                                                        Source:




                                                        ((expression))



                                                        The expression is evaluated according to the rules described below under ARITHMETIC EVALUATION. If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1. This is exactly equivalent to let "expression".








                                                        share|improve this answer












                                                        share|improve this answer



                                                        share|improve this answer










                                                        answered Jul 30 '18 at 18:19









                                                        CykerCyker

                                                        1,50521531




                                                        1,50521531























                                                            -1














                                                            The correct syntax is if ! $bool; then [statements]; fi.



                                                            Example:



                                                            bool=false

                                                            if ! $bool; then
                                                            echo "This is correct!"
                                                            fi

                                                            if [ ! $bool ]; then
                                                            echo "This is wrong!"
                                                            fi


                                                            Output: This is correct!






                                                            share|improve this answer
























                                                            • There’s a kernel of truth in your answer, but, lacking any explanation, it causes more confusion than it remedies.  Also, it is little more than a repeat of one of the previous answers.  If you don’t want your answer to be removed, explain why it is right.

                                                              – G-Man
                                                              May 24 '15 at 6:17
















                                                            -1














                                                            The correct syntax is if ! $bool; then [statements]; fi.



                                                            Example:



                                                            bool=false

                                                            if ! $bool; then
                                                            echo "This is correct!"
                                                            fi

                                                            if [ ! $bool ]; then
                                                            echo "This is wrong!"
                                                            fi


                                                            Output: This is correct!






                                                            share|improve this answer
























                                                            • There’s a kernel of truth in your answer, but, lacking any explanation, it causes more confusion than it remedies.  Also, it is little more than a repeat of one of the previous answers.  If you don’t want your answer to be removed, explain why it is right.

                                                              – G-Man
                                                              May 24 '15 at 6:17














                                                            -1












                                                            -1








                                                            -1







                                                            The correct syntax is if ! $bool; then [statements]; fi.



                                                            Example:



                                                            bool=false

                                                            if ! $bool; then
                                                            echo "This is correct!"
                                                            fi

                                                            if [ ! $bool ]; then
                                                            echo "This is wrong!"
                                                            fi


                                                            Output: This is correct!






                                                            share|improve this answer













                                                            The correct syntax is if ! $bool; then [statements]; fi.



                                                            Example:



                                                            bool=false

                                                            if ! $bool; then
                                                            echo "This is correct!"
                                                            fi

                                                            if [ ! $bool ]; then
                                                            echo "This is wrong!"
                                                            fi


                                                            Output: This is correct!







                                                            share|improve this answer












                                                            share|improve this answer



                                                            share|improve this answer










                                                            answered May 24 '15 at 5:45









                                                            James KoJames Ko

                                                            1403




                                                            1403













                                                            • There’s a kernel of truth in your answer, but, lacking any explanation, it causes more confusion than it remedies.  Also, it is little more than a repeat of one of the previous answers.  If you don’t want your answer to be removed, explain why it is right.

                                                              – G-Man
                                                              May 24 '15 at 6:17



















                                                            • There’s a kernel of truth in your answer, but, lacking any explanation, it causes more confusion than it remedies.  Also, it is little more than a repeat of one of the previous answers.  If you don’t want your answer to be removed, explain why it is right.

                                                              – G-Man
                                                              May 24 '15 at 6:17

















                                                            There’s a kernel of truth in your answer, but, lacking any explanation, it causes more confusion than it remedies.  Also, it is little more than a repeat of one of the previous answers.  If you don’t want your answer to be removed, explain why it is right.

                                                            – G-Man
                                                            May 24 '15 at 6:17





                                                            There’s a kernel of truth in your answer, but, lacking any explanation, it causes more confusion than it remedies.  Also, it is little more than a repeat of one of the previous answers.  If you don’t want your answer to be removed, explain why it is right.

                                                            – G-Man
                                                            May 24 '15 at 6:17



                                                            Popular posts from this blog

                                                            Loup dans la culture

                                                            How to solve the problem of ntp “Unable to contact time server” from KDE?

                                                            Connection limited (no internet access)