Bash Equality Operators ( == , -eq )












75















Can someone please explain the difference between -eq and == in bash scripting?



Is there any difference between the following?



[ $a -eq $b ]
and [ $a == $b ]



Is it simply that == is only used when the variables contain numbers?










share|improve this question





























    75















    Can someone please explain the difference between -eq and == in bash scripting?



    Is there any difference between the following?



    [ $a -eq $b ]
    and [ $a == $b ]



    Is it simply that == is only used when the variables contain numbers?










    share|improve this question



























      75












      75








      75


      18






      Can someone please explain the difference between -eq and == in bash scripting?



      Is there any difference between the following?



      [ $a -eq $b ]
      and [ $a == $b ]



      Is it simply that == is only used when the variables contain numbers?










      share|improve this question
















      Can someone please explain the difference between -eq and == in bash scripting?



      Is there any difference between the following?



      [ $a -eq $b ]
      and [ $a == $b ]



      Is it simply that == is only used when the variables contain numbers?







      bash






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Oct 25 '17 at 21:24









      guaka

      10.5k74481




      10.5k74481










      asked Dec 8 '13 at 3:29









      Victor BrunellVictor Brunell

      1,23541835




      1,23541835
























          4 Answers
          4






          active

          oldest

          votes


















          101














          It's the other way around: == is for string comparisons, -eq is for numeric ones. -eq is in the same family as -lt, -le, -gt, -ge, and -ne, if that helps you remember which is which.



          $ [ a == a ]; echo $?
          0
          $ [ a -eq a ]; echo $?
          -bash: [: a: integer expression expected
          2


          == is a bash-ism. The POSIX form is =. If portability to non-bash shells is important, use =.






          share|improve this answer





















          • 1





            Even if portability is not an immediate concern, I see no benefit from using the nonportable longer Bash-only form.

            – tripleee
            Nov 19 '18 at 7:56



















          19














          == is a bash-specific alias for = and it performs a string (lexical) comparison instead of a numeric comparison. eq being a numeric comparison of course.



          Finally, I usually prefer to use the form if [ "$a" == "$b" ]






          share|improve this answer



















          • 8





            Using == here is bad form, as only = is specified by POSIX.

            – Charles Duffy
            Oct 19 '15 at 5:45






          • 5





            If you really insist to use == then put it in between [[ and ]]. (And make sure that the first line of your script specifies to use /bin/bash.)

            – holgero
            Dec 21 '15 at 20:28





















          12














          It depends on the Test Construct around the operator. Your options are double parenthesis, double braces, single braces, or test



          If you use ((...)), you are testing arithmetic equity with == as in C:



          $ (( 1==1 )); echo $?
          0
          $ (( 1==2 )); echo $?
          1


          (Note: 0 means true in the Unix sense and non zero is a failed test)



          Using -eq inside of double parenthesis is a syntax error.



          If you are using [...] (or single brace) or [[...]] (or double brace), or test you can use one of -eq, -ne, -lt, -le, -gt, or -ge as an arithmetic comparison.



          $ [ 1 -eq 1 ]; echo $?
          0
          $ [ 1 -eq 2 ]; echo $?
          1
          $ test 1 -eq 1; echo $?
          0


          The == inside of single or double braces (or test command) is one of the string comparison operators:



          $ [[ "abc" == "abc" ]]; echo $?
          0
          $ [[ "abc" == "ABC" ]]; echo $?
          1


          As a string operator, = is equivalent to == and note the whitespace around = or == its required.



          While you can do [[ 1 == 1 ]] or [[ $(( 1+1 )) == 2 ]] it is testing the string equality -- not the arithmetic equality.



          So -eq produces the result probably expected that the integer value of 1+1 is equal to 2 even though the RH is a string and has a trailing space:



          $ [[ $(( 1+1 )) -eq  "2 " ]]; echo $?
          0


          While a string comparison of the same picks up the trailing space and therefor the string comparison fails:



          $ [[ $(( 1+1 )) ==  "2 " ]]; echo $?
          1


          And a mistaken string comparison can produce the complete wrong answer. '10' is lexicographically less than '2', so a string comparison returns true or 0. So many are bitten by this bug:



          $ [[ 10 < 2 ]]; echo $?
          0


          vs the correct test for 10 being arithmetically less than 2:



          $ [[ 10 -lt 2 ]]; echo $?
          1




          In comments, there is a question of the technical reason using the integer -eq on strings returns True for strings that are not the same:



          $ [[ "yes" -eq "no" ]]; echo $?
          0


          The reason is that Bash is untyped. The -eq causes the strings to be interpreted as integers if possible including base conversion:



          $ [[ "0x10" -eq 16 ]]; echo $?
          0
          $ [[ "010" -eq 8 ]]; echo $?
          0
          $ [[ "100" -eq 100 ]]; echo $?
          0


          And 0 if Bash thinks it is just a string:



          $ [[ "yes" -eq 0 ]]; echo $?
          0
          $ [[ "yes" -eq 1 ]]; echo $?
          1


          So [[ "yes" -eq "no" ]] is equivalent to [[ 0 -eq 0 ]]



          Last note: Many of the Bash specific extensions to the Test Constructs are not POSIX and therefore will fail in other shells. Other shells generally do not support [[...]] and ((...)) or ==.






          share|improve this answer


























          • I'm curious about the technical reason for [[ "yes" -eq "no" ]] returning True. How does bash coerce these strings to integer values that can be compared? ;-)

            – odony
            May 11 '17 at 14:42






          • 2





            Bash variables are untyped so [[ "yes" -eq "no" ]] is equivalent to [[ "yes" -eq 0 ]] or [[ "yes" -eq "any_noninteger_string" ]] -- All True. The -eq forces integer comparison. The"yes" is interpreted as a integer 0; the comparison is True if the other integer is either 0 or the string result is 0.

            – dawg
            May 12 '17 at 19:55













          • @odony: See update

            – dawg
            May 13 '17 at 15:05



















          5














          Guys: Several answers show dangerous examples. OP's example [ $a == $b ] specifically used unquoted variable substitution (as of Oct '17 edit). For [...] that is safe for string equality.



          But if you're going to enumerate alternatives like [[...]], you must inform also that the right-hand-side must be quoted. If not quoted, it is a pattern match! (From bash man page: "Any part of the pattern may be quoted to force it to be matched as a string.").



          Here in bash, the two statements yielding "yes" are pattern matching, other three are string equality:



          $ rht="A*"
          $ lft="AB"
          $ [ $lft = $rht ] && echo yes
          $ [ $lft == $rht ] && echo yes
          $ [[ $lft = $rht ]] && echo yes
          yes
          $ [[ $lft == $rht ]] && echo yes
          yes
          $ [[ $lft == "$rht" ]] && echo yes
          $





          share|improve this answer
























          • That's a dangerous gotcha, thanks for posting it!

            – joanis
            Jan 16 at 21:24











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f20449543%2fbash-equality-operators-eq%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          4 Answers
          4






          active

          oldest

          votes








          4 Answers
          4






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          101














          It's the other way around: == is for string comparisons, -eq is for numeric ones. -eq is in the same family as -lt, -le, -gt, -ge, and -ne, if that helps you remember which is which.



          $ [ a == a ]; echo $?
          0
          $ [ a -eq a ]; echo $?
          -bash: [: a: integer expression expected
          2


          == is a bash-ism. The POSIX form is =. If portability to non-bash shells is important, use =.






          share|improve this answer





















          • 1





            Even if portability is not an immediate concern, I see no benefit from using the nonportable longer Bash-only form.

            – tripleee
            Nov 19 '18 at 7:56
















          101














          It's the other way around: == is for string comparisons, -eq is for numeric ones. -eq is in the same family as -lt, -le, -gt, -ge, and -ne, if that helps you remember which is which.



          $ [ a == a ]; echo $?
          0
          $ [ a -eq a ]; echo $?
          -bash: [: a: integer expression expected
          2


          == is a bash-ism. The POSIX form is =. If portability to non-bash shells is important, use =.






          share|improve this answer





















          • 1





            Even if portability is not an immediate concern, I see no benefit from using the nonportable longer Bash-only form.

            – tripleee
            Nov 19 '18 at 7:56














          101












          101








          101







          It's the other way around: == is for string comparisons, -eq is for numeric ones. -eq is in the same family as -lt, -le, -gt, -ge, and -ne, if that helps you remember which is which.



          $ [ a == a ]; echo $?
          0
          $ [ a -eq a ]; echo $?
          -bash: [: a: integer expression expected
          2


          == is a bash-ism. The POSIX form is =. If portability to non-bash shells is important, use =.






          share|improve this answer















          It's the other way around: == is for string comparisons, -eq is for numeric ones. -eq is in the same family as -lt, -le, -gt, -ge, and -ne, if that helps you remember which is which.



          $ [ a == a ]; echo $?
          0
          $ [ a -eq a ]; echo $?
          -bash: [: a: integer expression expected
          2


          == is a bash-ism. The POSIX form is =. If portability to non-bash shells is important, use =.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 4 '16 at 21:21









          mklement0

          129k20242271




          129k20242271










          answered Dec 8 '13 at 3:31









          John KugelmanJohn Kugelman

          241k53401455




          241k53401455








          • 1





            Even if portability is not an immediate concern, I see no benefit from using the nonportable longer Bash-only form.

            – tripleee
            Nov 19 '18 at 7:56














          • 1





            Even if portability is not an immediate concern, I see no benefit from using the nonportable longer Bash-only form.

            – tripleee
            Nov 19 '18 at 7:56








          1




          1





          Even if portability is not an immediate concern, I see no benefit from using the nonportable longer Bash-only form.

          – tripleee
          Nov 19 '18 at 7:56





          Even if portability is not an immediate concern, I see no benefit from using the nonportable longer Bash-only form.

          – tripleee
          Nov 19 '18 at 7:56













          19














          == is a bash-specific alias for = and it performs a string (lexical) comparison instead of a numeric comparison. eq being a numeric comparison of course.



          Finally, I usually prefer to use the form if [ "$a" == "$b" ]






          share|improve this answer



















          • 8





            Using == here is bad form, as only = is specified by POSIX.

            – Charles Duffy
            Oct 19 '15 at 5:45






          • 5





            If you really insist to use == then put it in between [[ and ]]. (And make sure that the first line of your script specifies to use /bin/bash.)

            – holgero
            Dec 21 '15 at 20:28


















          19














          == is a bash-specific alias for = and it performs a string (lexical) comparison instead of a numeric comparison. eq being a numeric comparison of course.



          Finally, I usually prefer to use the form if [ "$a" == "$b" ]






          share|improve this answer



















          • 8





            Using == here is bad form, as only = is specified by POSIX.

            – Charles Duffy
            Oct 19 '15 at 5:45






          • 5





            If you really insist to use == then put it in between [[ and ]]. (And make sure that the first line of your script specifies to use /bin/bash.)

            – holgero
            Dec 21 '15 at 20:28
















          19












          19








          19







          == is a bash-specific alias for = and it performs a string (lexical) comparison instead of a numeric comparison. eq being a numeric comparison of course.



          Finally, I usually prefer to use the form if [ "$a" == "$b" ]






          share|improve this answer













          == is a bash-specific alias for = and it performs a string (lexical) comparison instead of a numeric comparison. eq being a numeric comparison of course.



          Finally, I usually prefer to use the form if [ "$a" == "$b" ]







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Dec 8 '13 at 3:33









          Elliott FrischElliott Frisch

          154k1391180




          154k1391180








          • 8





            Using == here is bad form, as only = is specified by POSIX.

            – Charles Duffy
            Oct 19 '15 at 5:45






          • 5





            If you really insist to use == then put it in between [[ and ]]. (And make sure that the first line of your script specifies to use /bin/bash.)

            – holgero
            Dec 21 '15 at 20:28
















          • 8





            Using == here is bad form, as only = is specified by POSIX.

            – Charles Duffy
            Oct 19 '15 at 5:45






          • 5





            If you really insist to use == then put it in between [[ and ]]. (And make sure that the first line of your script specifies to use /bin/bash.)

            – holgero
            Dec 21 '15 at 20:28










          8




          8





          Using == here is bad form, as only = is specified by POSIX.

          – Charles Duffy
          Oct 19 '15 at 5:45





          Using == here is bad form, as only = is specified by POSIX.

          – Charles Duffy
          Oct 19 '15 at 5:45




          5




          5





          If you really insist to use == then put it in between [[ and ]]. (And make sure that the first line of your script specifies to use /bin/bash.)

          – holgero
          Dec 21 '15 at 20:28







          If you really insist to use == then put it in between [[ and ]]. (And make sure that the first line of your script specifies to use /bin/bash.)

          – holgero
          Dec 21 '15 at 20:28













          12














          It depends on the Test Construct around the operator. Your options are double parenthesis, double braces, single braces, or test



          If you use ((...)), you are testing arithmetic equity with == as in C:



          $ (( 1==1 )); echo $?
          0
          $ (( 1==2 )); echo $?
          1


          (Note: 0 means true in the Unix sense and non zero is a failed test)



          Using -eq inside of double parenthesis is a syntax error.



          If you are using [...] (or single brace) or [[...]] (or double brace), or test you can use one of -eq, -ne, -lt, -le, -gt, or -ge as an arithmetic comparison.



          $ [ 1 -eq 1 ]; echo $?
          0
          $ [ 1 -eq 2 ]; echo $?
          1
          $ test 1 -eq 1; echo $?
          0


          The == inside of single or double braces (or test command) is one of the string comparison operators:



          $ [[ "abc" == "abc" ]]; echo $?
          0
          $ [[ "abc" == "ABC" ]]; echo $?
          1


          As a string operator, = is equivalent to == and note the whitespace around = or == its required.



          While you can do [[ 1 == 1 ]] or [[ $(( 1+1 )) == 2 ]] it is testing the string equality -- not the arithmetic equality.



          So -eq produces the result probably expected that the integer value of 1+1 is equal to 2 even though the RH is a string and has a trailing space:



          $ [[ $(( 1+1 )) -eq  "2 " ]]; echo $?
          0


          While a string comparison of the same picks up the trailing space and therefor the string comparison fails:



          $ [[ $(( 1+1 )) ==  "2 " ]]; echo $?
          1


          And a mistaken string comparison can produce the complete wrong answer. '10' is lexicographically less than '2', so a string comparison returns true or 0. So many are bitten by this bug:



          $ [[ 10 < 2 ]]; echo $?
          0


          vs the correct test for 10 being arithmetically less than 2:



          $ [[ 10 -lt 2 ]]; echo $?
          1




          In comments, there is a question of the technical reason using the integer -eq on strings returns True for strings that are not the same:



          $ [[ "yes" -eq "no" ]]; echo $?
          0


          The reason is that Bash is untyped. The -eq causes the strings to be interpreted as integers if possible including base conversion:



          $ [[ "0x10" -eq 16 ]]; echo $?
          0
          $ [[ "010" -eq 8 ]]; echo $?
          0
          $ [[ "100" -eq 100 ]]; echo $?
          0


          And 0 if Bash thinks it is just a string:



          $ [[ "yes" -eq 0 ]]; echo $?
          0
          $ [[ "yes" -eq 1 ]]; echo $?
          1


          So [[ "yes" -eq "no" ]] is equivalent to [[ 0 -eq 0 ]]



          Last note: Many of the Bash specific extensions to the Test Constructs are not POSIX and therefore will fail in other shells. Other shells generally do not support [[...]] and ((...)) or ==.






          share|improve this answer


























          • I'm curious about the technical reason for [[ "yes" -eq "no" ]] returning True. How does bash coerce these strings to integer values that can be compared? ;-)

            – odony
            May 11 '17 at 14:42






          • 2





            Bash variables are untyped so [[ "yes" -eq "no" ]] is equivalent to [[ "yes" -eq 0 ]] or [[ "yes" -eq "any_noninteger_string" ]] -- All True. The -eq forces integer comparison. The"yes" is interpreted as a integer 0; the comparison is True if the other integer is either 0 or the string result is 0.

            – dawg
            May 12 '17 at 19:55













          • @odony: See update

            – dawg
            May 13 '17 at 15:05
















          12














          It depends on the Test Construct around the operator. Your options are double parenthesis, double braces, single braces, or test



          If you use ((...)), you are testing arithmetic equity with == as in C:



          $ (( 1==1 )); echo $?
          0
          $ (( 1==2 )); echo $?
          1


          (Note: 0 means true in the Unix sense and non zero is a failed test)



          Using -eq inside of double parenthesis is a syntax error.



          If you are using [...] (or single brace) or [[...]] (or double brace), or test you can use one of -eq, -ne, -lt, -le, -gt, or -ge as an arithmetic comparison.



          $ [ 1 -eq 1 ]; echo $?
          0
          $ [ 1 -eq 2 ]; echo $?
          1
          $ test 1 -eq 1; echo $?
          0


          The == inside of single or double braces (or test command) is one of the string comparison operators:



          $ [[ "abc" == "abc" ]]; echo $?
          0
          $ [[ "abc" == "ABC" ]]; echo $?
          1


          As a string operator, = is equivalent to == and note the whitespace around = or == its required.



          While you can do [[ 1 == 1 ]] or [[ $(( 1+1 )) == 2 ]] it is testing the string equality -- not the arithmetic equality.



          So -eq produces the result probably expected that the integer value of 1+1 is equal to 2 even though the RH is a string and has a trailing space:



          $ [[ $(( 1+1 )) -eq  "2 " ]]; echo $?
          0


          While a string comparison of the same picks up the trailing space and therefor the string comparison fails:



          $ [[ $(( 1+1 )) ==  "2 " ]]; echo $?
          1


          And a mistaken string comparison can produce the complete wrong answer. '10' is lexicographically less than '2', so a string comparison returns true or 0. So many are bitten by this bug:



          $ [[ 10 < 2 ]]; echo $?
          0


          vs the correct test for 10 being arithmetically less than 2:



          $ [[ 10 -lt 2 ]]; echo $?
          1




          In comments, there is a question of the technical reason using the integer -eq on strings returns True for strings that are not the same:



          $ [[ "yes" -eq "no" ]]; echo $?
          0


          The reason is that Bash is untyped. The -eq causes the strings to be interpreted as integers if possible including base conversion:



          $ [[ "0x10" -eq 16 ]]; echo $?
          0
          $ [[ "010" -eq 8 ]]; echo $?
          0
          $ [[ "100" -eq 100 ]]; echo $?
          0


          And 0 if Bash thinks it is just a string:



          $ [[ "yes" -eq 0 ]]; echo $?
          0
          $ [[ "yes" -eq 1 ]]; echo $?
          1


          So [[ "yes" -eq "no" ]] is equivalent to [[ 0 -eq 0 ]]



          Last note: Many of the Bash specific extensions to the Test Constructs are not POSIX and therefore will fail in other shells. Other shells generally do not support [[...]] and ((...)) or ==.






          share|improve this answer


























          • I'm curious about the technical reason for [[ "yes" -eq "no" ]] returning True. How does bash coerce these strings to integer values that can be compared? ;-)

            – odony
            May 11 '17 at 14:42






          • 2





            Bash variables are untyped so [[ "yes" -eq "no" ]] is equivalent to [[ "yes" -eq 0 ]] or [[ "yes" -eq "any_noninteger_string" ]] -- All True. The -eq forces integer comparison. The"yes" is interpreted as a integer 0; the comparison is True if the other integer is either 0 or the string result is 0.

            – dawg
            May 12 '17 at 19:55













          • @odony: See update

            – dawg
            May 13 '17 at 15:05














          12












          12








          12







          It depends on the Test Construct around the operator. Your options are double parenthesis, double braces, single braces, or test



          If you use ((...)), you are testing arithmetic equity with == as in C:



          $ (( 1==1 )); echo $?
          0
          $ (( 1==2 )); echo $?
          1


          (Note: 0 means true in the Unix sense and non zero is a failed test)



          Using -eq inside of double parenthesis is a syntax error.



          If you are using [...] (or single brace) or [[...]] (or double brace), or test you can use one of -eq, -ne, -lt, -le, -gt, or -ge as an arithmetic comparison.



          $ [ 1 -eq 1 ]; echo $?
          0
          $ [ 1 -eq 2 ]; echo $?
          1
          $ test 1 -eq 1; echo $?
          0


          The == inside of single or double braces (or test command) is one of the string comparison operators:



          $ [[ "abc" == "abc" ]]; echo $?
          0
          $ [[ "abc" == "ABC" ]]; echo $?
          1


          As a string operator, = is equivalent to == and note the whitespace around = or == its required.



          While you can do [[ 1 == 1 ]] or [[ $(( 1+1 )) == 2 ]] it is testing the string equality -- not the arithmetic equality.



          So -eq produces the result probably expected that the integer value of 1+1 is equal to 2 even though the RH is a string and has a trailing space:



          $ [[ $(( 1+1 )) -eq  "2 " ]]; echo $?
          0


          While a string comparison of the same picks up the trailing space and therefor the string comparison fails:



          $ [[ $(( 1+1 )) ==  "2 " ]]; echo $?
          1


          And a mistaken string comparison can produce the complete wrong answer. '10' is lexicographically less than '2', so a string comparison returns true or 0. So many are bitten by this bug:



          $ [[ 10 < 2 ]]; echo $?
          0


          vs the correct test for 10 being arithmetically less than 2:



          $ [[ 10 -lt 2 ]]; echo $?
          1




          In comments, there is a question of the technical reason using the integer -eq on strings returns True for strings that are not the same:



          $ [[ "yes" -eq "no" ]]; echo $?
          0


          The reason is that Bash is untyped. The -eq causes the strings to be interpreted as integers if possible including base conversion:



          $ [[ "0x10" -eq 16 ]]; echo $?
          0
          $ [[ "010" -eq 8 ]]; echo $?
          0
          $ [[ "100" -eq 100 ]]; echo $?
          0


          And 0 if Bash thinks it is just a string:



          $ [[ "yes" -eq 0 ]]; echo $?
          0
          $ [[ "yes" -eq 1 ]]; echo $?
          1


          So [[ "yes" -eq "no" ]] is equivalent to [[ 0 -eq 0 ]]



          Last note: Many of the Bash specific extensions to the Test Constructs are not POSIX and therefore will fail in other shells. Other shells generally do not support [[...]] and ((...)) or ==.






          share|improve this answer















          It depends on the Test Construct around the operator. Your options are double parenthesis, double braces, single braces, or test



          If you use ((...)), you are testing arithmetic equity with == as in C:



          $ (( 1==1 )); echo $?
          0
          $ (( 1==2 )); echo $?
          1


          (Note: 0 means true in the Unix sense and non zero is a failed test)



          Using -eq inside of double parenthesis is a syntax error.



          If you are using [...] (or single brace) or [[...]] (or double brace), or test you can use one of -eq, -ne, -lt, -le, -gt, or -ge as an arithmetic comparison.



          $ [ 1 -eq 1 ]; echo $?
          0
          $ [ 1 -eq 2 ]; echo $?
          1
          $ test 1 -eq 1; echo $?
          0


          The == inside of single or double braces (or test command) is one of the string comparison operators:



          $ [[ "abc" == "abc" ]]; echo $?
          0
          $ [[ "abc" == "ABC" ]]; echo $?
          1


          As a string operator, = is equivalent to == and note the whitespace around = or == its required.



          While you can do [[ 1 == 1 ]] or [[ $(( 1+1 )) == 2 ]] it is testing the string equality -- not the arithmetic equality.



          So -eq produces the result probably expected that the integer value of 1+1 is equal to 2 even though the RH is a string and has a trailing space:



          $ [[ $(( 1+1 )) -eq  "2 " ]]; echo $?
          0


          While a string comparison of the same picks up the trailing space and therefor the string comparison fails:



          $ [[ $(( 1+1 )) ==  "2 " ]]; echo $?
          1


          And a mistaken string comparison can produce the complete wrong answer. '10' is lexicographically less than '2', so a string comparison returns true or 0. So many are bitten by this bug:



          $ [[ 10 < 2 ]]; echo $?
          0


          vs the correct test for 10 being arithmetically less than 2:



          $ [[ 10 -lt 2 ]]; echo $?
          1




          In comments, there is a question of the technical reason using the integer -eq on strings returns True for strings that are not the same:



          $ [[ "yes" -eq "no" ]]; echo $?
          0


          The reason is that Bash is untyped. The -eq causes the strings to be interpreted as integers if possible including base conversion:



          $ [[ "0x10" -eq 16 ]]; echo $?
          0
          $ [[ "010" -eq 8 ]]; echo $?
          0
          $ [[ "100" -eq 100 ]]; echo $?
          0


          And 0 if Bash thinks it is just a string:



          $ [[ "yes" -eq 0 ]]; echo $?
          0
          $ [[ "yes" -eq 1 ]]; echo $?
          1


          So [[ "yes" -eq "no" ]] is equivalent to [[ 0 -eq 0 ]]



          Last note: Many of the Bash specific extensions to the Test Constructs are not POSIX and therefore will fail in other shells. Other shells generally do not support [[...]] and ((...)) or ==.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited May 13 '17 at 4:31

























          answered Nov 4 '16 at 20:37









          dawgdawg

          58.8k1183152




          58.8k1183152













          • I'm curious about the technical reason for [[ "yes" -eq "no" ]] returning True. How does bash coerce these strings to integer values that can be compared? ;-)

            – odony
            May 11 '17 at 14:42






          • 2





            Bash variables are untyped so [[ "yes" -eq "no" ]] is equivalent to [[ "yes" -eq 0 ]] or [[ "yes" -eq "any_noninteger_string" ]] -- All True. The -eq forces integer comparison. The"yes" is interpreted as a integer 0; the comparison is True if the other integer is either 0 or the string result is 0.

            – dawg
            May 12 '17 at 19:55













          • @odony: See update

            – dawg
            May 13 '17 at 15:05



















          • I'm curious about the technical reason for [[ "yes" -eq "no" ]] returning True. How does bash coerce these strings to integer values that can be compared? ;-)

            – odony
            May 11 '17 at 14:42






          • 2





            Bash variables are untyped so [[ "yes" -eq "no" ]] is equivalent to [[ "yes" -eq 0 ]] or [[ "yes" -eq "any_noninteger_string" ]] -- All True. The -eq forces integer comparison. The"yes" is interpreted as a integer 0; the comparison is True if the other integer is either 0 or the string result is 0.

            – dawg
            May 12 '17 at 19:55













          • @odony: See update

            – dawg
            May 13 '17 at 15:05

















          I'm curious about the technical reason for [[ "yes" -eq "no" ]] returning True. How does bash coerce these strings to integer values that can be compared? ;-)

          – odony
          May 11 '17 at 14:42





          I'm curious about the technical reason for [[ "yes" -eq "no" ]] returning True. How does bash coerce these strings to integer values that can be compared? ;-)

          – odony
          May 11 '17 at 14:42




          2




          2





          Bash variables are untyped so [[ "yes" -eq "no" ]] is equivalent to [[ "yes" -eq 0 ]] or [[ "yes" -eq "any_noninteger_string" ]] -- All True. The -eq forces integer comparison. The"yes" is interpreted as a integer 0; the comparison is True if the other integer is either 0 or the string result is 0.

          – dawg
          May 12 '17 at 19:55







          Bash variables are untyped so [[ "yes" -eq "no" ]] is equivalent to [[ "yes" -eq 0 ]] or [[ "yes" -eq "any_noninteger_string" ]] -- All True. The -eq forces integer comparison. The"yes" is interpreted as a integer 0; the comparison is True if the other integer is either 0 or the string result is 0.

          – dawg
          May 12 '17 at 19:55















          @odony: See update

          – dawg
          May 13 '17 at 15:05





          @odony: See update

          – dawg
          May 13 '17 at 15:05











          5














          Guys: Several answers show dangerous examples. OP's example [ $a == $b ] specifically used unquoted variable substitution (as of Oct '17 edit). For [...] that is safe for string equality.



          But if you're going to enumerate alternatives like [[...]], you must inform also that the right-hand-side must be quoted. If not quoted, it is a pattern match! (From bash man page: "Any part of the pattern may be quoted to force it to be matched as a string.").



          Here in bash, the two statements yielding "yes" are pattern matching, other three are string equality:



          $ rht="A*"
          $ lft="AB"
          $ [ $lft = $rht ] && echo yes
          $ [ $lft == $rht ] && echo yes
          $ [[ $lft = $rht ]] && echo yes
          yes
          $ [[ $lft == $rht ]] && echo yes
          yes
          $ [[ $lft == "$rht" ]] && echo yes
          $





          share|improve this answer
























          • That's a dangerous gotcha, thanks for posting it!

            – joanis
            Jan 16 at 21:24
















          5














          Guys: Several answers show dangerous examples. OP's example [ $a == $b ] specifically used unquoted variable substitution (as of Oct '17 edit). For [...] that is safe for string equality.



          But if you're going to enumerate alternatives like [[...]], you must inform also that the right-hand-side must be quoted. If not quoted, it is a pattern match! (From bash man page: "Any part of the pattern may be quoted to force it to be matched as a string.").



          Here in bash, the two statements yielding "yes" are pattern matching, other three are string equality:



          $ rht="A*"
          $ lft="AB"
          $ [ $lft = $rht ] && echo yes
          $ [ $lft == $rht ] && echo yes
          $ [[ $lft = $rht ]] && echo yes
          yes
          $ [[ $lft == $rht ]] && echo yes
          yes
          $ [[ $lft == "$rht" ]] && echo yes
          $





          share|improve this answer
























          • That's a dangerous gotcha, thanks for posting it!

            – joanis
            Jan 16 at 21:24














          5












          5








          5







          Guys: Several answers show dangerous examples. OP's example [ $a == $b ] specifically used unquoted variable substitution (as of Oct '17 edit). For [...] that is safe for string equality.



          But if you're going to enumerate alternatives like [[...]], you must inform also that the right-hand-side must be quoted. If not quoted, it is a pattern match! (From bash man page: "Any part of the pattern may be quoted to force it to be matched as a string.").



          Here in bash, the two statements yielding "yes" are pattern matching, other three are string equality:



          $ rht="A*"
          $ lft="AB"
          $ [ $lft = $rht ] && echo yes
          $ [ $lft == $rht ] && echo yes
          $ [[ $lft = $rht ]] && echo yes
          yes
          $ [[ $lft == $rht ]] && echo yes
          yes
          $ [[ $lft == "$rht" ]] && echo yes
          $





          share|improve this answer













          Guys: Several answers show dangerous examples. OP's example [ $a == $b ] specifically used unquoted variable substitution (as of Oct '17 edit). For [...] that is safe for string equality.



          But if you're going to enumerate alternatives like [[...]], you must inform also that the right-hand-side must be quoted. If not quoted, it is a pattern match! (From bash man page: "Any part of the pattern may be quoted to force it to be matched as a string.").



          Here in bash, the two statements yielding "yes" are pattern matching, other three are string equality:



          $ rht="A*"
          $ lft="AB"
          $ [ $lft = $rht ] && echo yes
          $ [ $lft == $rht ] && echo yes
          $ [[ $lft = $rht ]] && echo yes
          yes
          $ [[ $lft == $rht ]] && echo yes
          yes
          $ [[ $lft == "$rht" ]] && echo yes
          $






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Jan 15 '18 at 3:02









          bk-sebk-se

          19526




          19526













          • That's a dangerous gotcha, thanks for posting it!

            – joanis
            Jan 16 at 21:24



















          • That's a dangerous gotcha, thanks for posting it!

            – joanis
            Jan 16 at 21:24

















          That's a dangerous gotcha, thanks for posting it!

          – joanis
          Jan 16 at 21:24





          That's a dangerous gotcha, thanks for posting it!

          – joanis
          Jan 16 at 21:24


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f20449543%2fbash-equality-operators-eq%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Guess what letter conforming each word

          Port of Spain

          Run scheduled task as local user group (not BUILTIN)