Difference between [[ expr1 || expr2 ]] and [[ expr1 ]] || [[ expr2 ]]Difference between >> and >> operators?What's the difference between `` and $()?What's the difference between “==” and “=~”?What's the difference between $@ and $*Difference between / and //Difference between 1> and >Difference between `/` and `//` directoriesdifference between ~ and cdwhat are the differences between `==` and `=` in conditional expressions?Whats the difference between $_ and !$?

Players of unusual orchestral instruments

Is this floating-point optimization allowed?

Are there J.S. Bach pieces that do not start with the tonic chord?

Was the Ford Model T black because of the speed black paint dries?

Back to the nineties!

How does one stock fund's charge of 1% more in operating expenses than another fund lower expected returns by 10%?

Installing ubuntu with HD + SSD

Military Weapon System

Why hasn't the U.S. government paid war reparations to any country it attacked?

What happens if you cast Dissonant Whispers on a Hydra?

nginx serves wrong domain site. It doenst shows default site if no configuration applies

What does "Fotze" really mean?

Report how much space is used and available in storage in ZFS on FreeBSD

Metric version of "footage"?

To accent or not to accent in Greek

How to determine port and starboard on a rotating wheel space station?

How can an advanced civilization forget how to manufacture its technology?

Was adding milk to tea started to reduce employee tea break time?

Is Arc Length always irrational between two rational points?

Why did the Japanese attack the Aleutians at the same time as Midway?

Filtering fine silt/mud from water (not necessarily bacteria etc.)

Is `curl something | sudo bash -` a reasonably safe installation method?

Mistakenly modified `/bin/sh'

How to check the quality of an audio sample?



Difference between [[ expr1 || expr2 ]] and [[ expr1 ]] || [[ expr2 ]]


Difference between >> and >> operators?What's the difference between `` and $()?What's the difference between “==” and “=~”?What's the difference between $@ and $*Difference between / and //Difference between 1> and >Difference between `/` and `//` directoriesdifference between ~ and cdwhat are the differences between `==` and `=` in conditional expressions?Whats the difference between $_ and !$?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








8















Consider two conditional expressions expr1 and expr2, for example $i -eq $j and $k -eq $l. We can write this in bash a number of ways. Here are two possibilities



[[ expr1 || expr2 ]]

[[ expr1 ]] || [[ expr2 ]]


I'm fairly sure I've seen recommendations here that the second should be preferred, but I can't find evidence to support this.



Here is a sample script that seems to demonstrate there is no difference:



for i in 0 1
do
for j in 0 1
do
for k in 0 1
do
for l in 0 1
do
if [[ $i -eq $j || $k -eq $l ]]; then printf "1-yest"; else printf "1-not"; fi
if [[ $i -eq $j ]] || [[ $k -eq $l ]]; then printf "2-yesn"; else printf "2-non"; fi
done
done
done
done


and output showing that both condition constructs produce the same result:



1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-no 2-no
1-no 2-no
1-yes 2-yes
1-yes 2-yes
1-no 2-no
1-no 2-no
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes


Is there any benefit to using one construct over the other?



For bonus points, same question but generalising to multiple conditions using || and &&. For example, [[ expr1 && expr2 || expr3 ]].










share|improve this question






















  • With respect to why recommendations of this type are often given wrt. [ or test (not [[), search for the OB tags (linked to the "obsolescent" definition) in the POSIX spec for test. In test, there are some pathological cases where it can be impossible to tell if ( or ) is meant to be syntax meaningful to the test command or a string to be tested, so people who ignore the obsolescence markers and use that syntax can actually need the otherwise-obsolete "x$foo" practice; with [[, that isn't a problem.

    – Charles Duffy
    Jul 5 at 22:07


















8















Consider two conditional expressions expr1 and expr2, for example $i -eq $j and $k -eq $l. We can write this in bash a number of ways. Here are two possibilities



[[ expr1 || expr2 ]]

[[ expr1 ]] || [[ expr2 ]]


I'm fairly sure I've seen recommendations here that the second should be preferred, but I can't find evidence to support this.



Here is a sample script that seems to demonstrate there is no difference:



for i in 0 1
do
for j in 0 1
do
for k in 0 1
do
for l in 0 1
do
if [[ $i -eq $j || $k -eq $l ]]; then printf "1-yest"; else printf "1-not"; fi
if [[ $i -eq $j ]] || [[ $k -eq $l ]]; then printf "2-yesn"; else printf "2-non"; fi
done
done
done
done


and output showing that both condition constructs produce the same result:



1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-no 2-no
1-no 2-no
1-yes 2-yes
1-yes 2-yes
1-no 2-no
1-no 2-no
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes


Is there any benefit to using one construct over the other?



For bonus points, same question but generalising to multiple conditions using || and &&. For example, [[ expr1 && expr2 || expr3 ]].










share|improve this question






















  • With respect to why recommendations of this type are often given wrt. [ or test (not [[), search for the OB tags (linked to the "obsolescent" definition) in the POSIX spec for test. In test, there are some pathological cases where it can be impossible to tell if ( or ) is meant to be syntax meaningful to the test command or a string to be tested, so people who ignore the obsolescence markers and use that syntax can actually need the otherwise-obsolete "x$foo" practice; with [[, that isn't a problem.

    – Charles Duffy
    Jul 5 at 22:07














8












8








8


0






Consider two conditional expressions expr1 and expr2, for example $i -eq $j and $k -eq $l. We can write this in bash a number of ways. Here are two possibilities



[[ expr1 || expr2 ]]

[[ expr1 ]] || [[ expr2 ]]


I'm fairly sure I've seen recommendations here that the second should be preferred, but I can't find evidence to support this.



Here is a sample script that seems to demonstrate there is no difference:



for i in 0 1
do
for j in 0 1
do
for k in 0 1
do
for l in 0 1
do
if [[ $i -eq $j || $k -eq $l ]]; then printf "1-yest"; else printf "1-not"; fi
if [[ $i -eq $j ]] || [[ $k -eq $l ]]; then printf "2-yesn"; else printf "2-non"; fi
done
done
done
done


and output showing that both condition constructs produce the same result:



1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-no 2-no
1-no 2-no
1-yes 2-yes
1-yes 2-yes
1-no 2-no
1-no 2-no
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes


Is there any benefit to using one construct over the other?



For bonus points, same question but generalising to multiple conditions using || and &&. For example, [[ expr1 && expr2 || expr3 ]].










share|improve this question














Consider two conditional expressions expr1 and expr2, for example $i -eq $j and $k -eq $l. We can write this in bash a number of ways. Here are two possibilities



[[ expr1 || expr2 ]]

[[ expr1 ]] || [[ expr2 ]]


I'm fairly sure I've seen recommendations here that the second should be preferred, but I can't find evidence to support this.



Here is a sample script that seems to demonstrate there is no difference:



for i in 0 1
do
for j in 0 1
do
for k in 0 1
do
for l in 0 1
do
if [[ $i -eq $j || $k -eq $l ]]; then printf "1-yest"; else printf "1-not"; fi
if [[ $i -eq $j ]] || [[ $k -eq $l ]]; then printf "2-yesn"; else printf "2-non"; fi
done
done
done
done


and output showing that both condition constructs produce the same result:



1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-no 2-no
1-no 2-no
1-yes 2-yes
1-yes 2-yes
1-no 2-no
1-no 2-no
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes


Is there any benefit to using one construct over the other?



For bonus points, same question but generalising to multiple conditions using || and &&. For example, [[ expr1 && expr2 || expr3 ]].







bash






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Jul 5 at 10:02









roaimaroaima

48.2k7 gold badges63 silver badges131 bronze badges




48.2k7 gold badges63 silver badges131 bronze badges












  • With respect to why recommendations of this type are often given wrt. [ or test (not [[), search for the OB tags (linked to the "obsolescent" definition) in the POSIX spec for test. In test, there are some pathological cases where it can be impossible to tell if ( or ) is meant to be syntax meaningful to the test command or a string to be tested, so people who ignore the obsolescence markers and use that syntax can actually need the otherwise-obsolete "x$foo" practice; with [[, that isn't a problem.

    – Charles Duffy
    Jul 5 at 22:07


















  • With respect to why recommendations of this type are often given wrt. [ or test (not [[), search for the OB tags (linked to the "obsolescent" definition) in the POSIX spec for test. In test, there are some pathological cases where it can be impossible to tell if ( or ) is meant to be syntax meaningful to the test command or a string to be tested, so people who ignore the obsolescence markers and use that syntax can actually need the otherwise-obsolete "x$foo" practice; with [[, that isn't a problem.

    – Charles Duffy
    Jul 5 at 22:07

















With respect to why recommendations of this type are often given wrt. [ or test (not [[), search for the OB tags (linked to the "obsolescent" definition) in the POSIX spec for test. In test, there are some pathological cases where it can be impossible to tell if ( or ) is meant to be syntax meaningful to the test command or a string to be tested, so people who ignore the obsolescence markers and use that syntax can actually need the otherwise-obsolete "x$foo" practice; with [[, that isn't a problem.

– Charles Duffy
Jul 5 at 22:07






With respect to why recommendations of this type are often given wrt. [ or test (not [[), search for the OB tags (linked to the "obsolescent" definition) in the POSIX spec for test. In test, there are some pathological cases where it can be impossible to tell if ( or ) is meant to be syntax meaningful to the test command or a string to be tested, so people who ignore the obsolescence markers and use that syntax can actually need the otherwise-obsolete "x$foo" practice; with [[, that isn't a problem.

– Charles Duffy
Jul 5 at 22:07











1 Answer
1






active

oldest

votes


















7














I think the recommendation you saw was for POSIX sh and/or the test command which doubles as the [ command, rather than the [[ construct which appeared in ksh (thanks Stéphane Chazelas for the tip) and is also used for example in bash, zsh and some other shells.



In most languages, like C, when a clause is already known to be true or false, there's no need to evaluate the remainder parts depending on the operation: if true not after a logical or following it, if false not after a logical and, etc. This of course allows for example to stop when a pointer is NULL and not try to dereference it in the next clause.



But sh's [ expr1 -o expr2 ] construct (including bash's implementation) doesn't do this: it always evaluates both sides, when one would want only expr1 to be evaluated. This might have been done for compatibility with the test command implementation. On the other hand, sh's || and && do follow the usual principle: not evaluated if it won't change the result.



So the difference to note would be:



: > /tmp/effect #clear effect
if [ 1 -eq 1 -o $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect


which yields:



true
or-was-evaluated


Above, each [ could have been replaced with /usr/bin/[ which is an alias to the test command, used before [ was made built-in to shells.



While the two next constructs:



: > /tmp/effect #clear effect
if [ 1 -eq 1 ] || [ $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect


or



: > /tmp/effect #clear effect
if [[ 1 -eq 1 || $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]]; then
echo true;
fi
cat /tmp/effect


Will only yield true and leave effect empty: || behaves correctly, and [[ corrected this issue too.




UPDATE:



As @StéphaneChazelas commented, I missed several differences related to the initial question. I'll just put here the most important one (at least to me): priority of operators.



While the shell will not considere precedence:



if true || true && false; then
echo true
else
echo false
fi


yields (because there is no precedence and thus first true || true is evaluated, and then && false):



false


inside [[ ]] the && operator has precedence over ||:



if [[ 1 -eq 1 || 1 -eq 1 && 1 -eq 0 ]]; then
echo true
else
echo false
fi


yields (because 1 -eq 1 && 1 -eq 0 is grouped and is thus the 2nd member of ||):



true


at least for ksh, bash, zsh.



So [[ ]] has improved behaviour over both [ ] and direct shell logical operators.






share|improve this answer




















  • 1





    [ x -o y ] doesn't have to evaluate both side. While GNU test or the [ builtin of bash do, you'd find with strace zsh -c '[ x -o -f /x ]' that [ doesn't try to stat() /x. Same with mksh. But it's true that -o and -a are severely broken, can't be used reliably and are deprecated by POSIX.

    – Stéphane Chazelas
    Jul 5 at 11:20







  • 1





    One difference is that inside [[...]], && has higher precedence than ||, while outside they have equal precedence. Compare ksh -c '[[ x || x && "" ]]' vs sh -c 'true || true && false'

    – Stéphane Chazelas
    Jul 5 at 11:24






  • 1





    Note that the standard [ / test utility doesn't have a == operator. The equality operator is = (note that inside ksh's [[...]], =/== are not equality operators, but pattern matching ones).

    – Stéphane Chazelas
    Jul 5 at 11:26






  • 1





    It's the other way round. && has precedence over || inside [[...]] (or ((...))) but not the && and || shell operators. [[ x || y && z ]] is x || (y && z) while x || y && z is (x || y) && z (operators evaluated left to right without precedence). Similar to how * has precedence over + (1 + 2 * 3 is 1 + (2 * 3)) but + and - have same precedence.

    – Stéphane Chazelas
    Jul 5 at 13:04







  • 1





    If && has precedence over ||, then it should be true || (true && false), instead of (true || true) && false

    – Prvt_Yadv
    Jul 5 at 13:11













Your Answer








StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
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: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
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%2funix.stackexchange.com%2fquestions%2f528505%2fdifference-between-expr1-expr2-and-expr1-expr2%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









7














I think the recommendation you saw was for POSIX sh and/or the test command which doubles as the [ command, rather than the [[ construct which appeared in ksh (thanks Stéphane Chazelas for the tip) and is also used for example in bash, zsh and some other shells.



In most languages, like C, when a clause is already known to be true or false, there's no need to evaluate the remainder parts depending on the operation: if true not after a logical or following it, if false not after a logical and, etc. This of course allows for example to stop when a pointer is NULL and not try to dereference it in the next clause.



But sh's [ expr1 -o expr2 ] construct (including bash's implementation) doesn't do this: it always evaluates both sides, when one would want only expr1 to be evaluated. This might have been done for compatibility with the test command implementation. On the other hand, sh's || and && do follow the usual principle: not evaluated if it won't change the result.



So the difference to note would be:



: > /tmp/effect #clear effect
if [ 1 -eq 1 -o $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect


which yields:



true
or-was-evaluated


Above, each [ could have been replaced with /usr/bin/[ which is an alias to the test command, used before [ was made built-in to shells.



While the two next constructs:



: > /tmp/effect #clear effect
if [ 1 -eq 1 ] || [ $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect


or



: > /tmp/effect #clear effect
if [[ 1 -eq 1 || $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]]; then
echo true;
fi
cat /tmp/effect


Will only yield true and leave effect empty: || behaves correctly, and [[ corrected this issue too.




UPDATE:



As @StéphaneChazelas commented, I missed several differences related to the initial question. I'll just put here the most important one (at least to me): priority of operators.



While the shell will not considere precedence:



if true || true && false; then
echo true
else
echo false
fi


yields (because there is no precedence and thus first true || true is evaluated, and then && false):



false


inside [[ ]] the && operator has precedence over ||:



if [[ 1 -eq 1 || 1 -eq 1 && 1 -eq 0 ]]; then
echo true
else
echo false
fi


yields (because 1 -eq 1 && 1 -eq 0 is grouped and is thus the 2nd member of ||):



true


at least for ksh, bash, zsh.



So [[ ]] has improved behaviour over both [ ] and direct shell logical operators.






share|improve this answer




















  • 1





    [ x -o y ] doesn't have to evaluate both side. While GNU test or the [ builtin of bash do, you'd find with strace zsh -c '[ x -o -f /x ]' that [ doesn't try to stat() /x. Same with mksh. But it's true that -o and -a are severely broken, can't be used reliably and are deprecated by POSIX.

    – Stéphane Chazelas
    Jul 5 at 11:20







  • 1





    One difference is that inside [[...]], && has higher precedence than ||, while outside they have equal precedence. Compare ksh -c '[[ x || x && "" ]]' vs sh -c 'true || true && false'

    – Stéphane Chazelas
    Jul 5 at 11:24






  • 1





    Note that the standard [ / test utility doesn't have a == operator. The equality operator is = (note that inside ksh's [[...]], =/== are not equality operators, but pattern matching ones).

    – Stéphane Chazelas
    Jul 5 at 11:26






  • 1





    It's the other way round. && has precedence over || inside [[...]] (or ((...))) but not the && and || shell operators. [[ x || y && z ]] is x || (y && z) while x || y && z is (x || y) && z (operators evaluated left to right without precedence). Similar to how * has precedence over + (1 + 2 * 3 is 1 + (2 * 3)) but + and - have same precedence.

    – Stéphane Chazelas
    Jul 5 at 13:04







  • 1





    If && has precedence over ||, then it should be true || (true && false), instead of (true || true) && false

    – Prvt_Yadv
    Jul 5 at 13:11















7














I think the recommendation you saw was for POSIX sh and/or the test command which doubles as the [ command, rather than the [[ construct which appeared in ksh (thanks Stéphane Chazelas for the tip) and is also used for example in bash, zsh and some other shells.



In most languages, like C, when a clause is already known to be true or false, there's no need to evaluate the remainder parts depending on the operation: if true not after a logical or following it, if false not after a logical and, etc. This of course allows for example to stop when a pointer is NULL and not try to dereference it in the next clause.



But sh's [ expr1 -o expr2 ] construct (including bash's implementation) doesn't do this: it always evaluates both sides, when one would want only expr1 to be evaluated. This might have been done for compatibility with the test command implementation. On the other hand, sh's || and && do follow the usual principle: not evaluated if it won't change the result.



So the difference to note would be:



: > /tmp/effect #clear effect
if [ 1 -eq 1 -o $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect


which yields:



true
or-was-evaluated


Above, each [ could have been replaced with /usr/bin/[ which is an alias to the test command, used before [ was made built-in to shells.



While the two next constructs:



: > /tmp/effect #clear effect
if [ 1 -eq 1 ] || [ $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect


or



: > /tmp/effect #clear effect
if [[ 1 -eq 1 || $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]]; then
echo true;
fi
cat /tmp/effect


Will only yield true and leave effect empty: || behaves correctly, and [[ corrected this issue too.




UPDATE:



As @StéphaneChazelas commented, I missed several differences related to the initial question. I'll just put here the most important one (at least to me): priority of operators.



While the shell will not considere precedence:



if true || true && false; then
echo true
else
echo false
fi


yields (because there is no precedence and thus first true || true is evaluated, and then && false):



false


inside [[ ]] the && operator has precedence over ||:



if [[ 1 -eq 1 || 1 -eq 1 && 1 -eq 0 ]]; then
echo true
else
echo false
fi


yields (because 1 -eq 1 && 1 -eq 0 is grouped and is thus the 2nd member of ||):



true


at least for ksh, bash, zsh.



So [[ ]] has improved behaviour over both [ ] and direct shell logical operators.






share|improve this answer




















  • 1





    [ x -o y ] doesn't have to evaluate both side. While GNU test or the [ builtin of bash do, you'd find with strace zsh -c '[ x -o -f /x ]' that [ doesn't try to stat() /x. Same with mksh. But it's true that -o and -a are severely broken, can't be used reliably and are deprecated by POSIX.

    – Stéphane Chazelas
    Jul 5 at 11:20







  • 1





    One difference is that inside [[...]], && has higher precedence than ||, while outside they have equal precedence. Compare ksh -c '[[ x || x && "" ]]' vs sh -c 'true || true && false'

    – Stéphane Chazelas
    Jul 5 at 11:24






  • 1





    Note that the standard [ / test utility doesn't have a == operator. The equality operator is = (note that inside ksh's [[...]], =/== are not equality operators, but pattern matching ones).

    – Stéphane Chazelas
    Jul 5 at 11:26






  • 1





    It's the other way round. && has precedence over || inside [[...]] (or ((...))) but not the && and || shell operators. [[ x || y && z ]] is x || (y && z) while x || y && z is (x || y) && z (operators evaluated left to right without precedence). Similar to how * has precedence over + (1 + 2 * 3 is 1 + (2 * 3)) but + and - have same precedence.

    – Stéphane Chazelas
    Jul 5 at 13:04







  • 1





    If && has precedence over ||, then it should be true || (true && false), instead of (true || true) && false

    – Prvt_Yadv
    Jul 5 at 13:11













7












7








7







I think the recommendation you saw was for POSIX sh and/or the test command which doubles as the [ command, rather than the [[ construct which appeared in ksh (thanks Stéphane Chazelas for the tip) and is also used for example in bash, zsh and some other shells.



In most languages, like C, when a clause is already known to be true or false, there's no need to evaluate the remainder parts depending on the operation: if true not after a logical or following it, if false not after a logical and, etc. This of course allows for example to stop when a pointer is NULL and not try to dereference it in the next clause.



But sh's [ expr1 -o expr2 ] construct (including bash's implementation) doesn't do this: it always evaluates both sides, when one would want only expr1 to be evaluated. This might have been done for compatibility with the test command implementation. On the other hand, sh's || and && do follow the usual principle: not evaluated if it won't change the result.



So the difference to note would be:



: > /tmp/effect #clear effect
if [ 1 -eq 1 -o $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect


which yields:



true
or-was-evaluated


Above, each [ could have been replaced with /usr/bin/[ which is an alias to the test command, used before [ was made built-in to shells.



While the two next constructs:



: > /tmp/effect #clear effect
if [ 1 -eq 1 ] || [ $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect


or



: > /tmp/effect #clear effect
if [[ 1 -eq 1 || $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]]; then
echo true;
fi
cat /tmp/effect


Will only yield true and leave effect empty: || behaves correctly, and [[ corrected this issue too.




UPDATE:



As @StéphaneChazelas commented, I missed several differences related to the initial question. I'll just put here the most important one (at least to me): priority of operators.



While the shell will not considere precedence:



if true || true && false; then
echo true
else
echo false
fi


yields (because there is no precedence and thus first true || true is evaluated, and then && false):



false


inside [[ ]] the && operator has precedence over ||:



if [[ 1 -eq 1 || 1 -eq 1 && 1 -eq 0 ]]; then
echo true
else
echo false
fi


yields (because 1 -eq 1 && 1 -eq 0 is grouped and is thus the 2nd member of ||):



true


at least for ksh, bash, zsh.



So [[ ]] has improved behaviour over both [ ] and direct shell logical operators.






share|improve this answer















I think the recommendation you saw was for POSIX sh and/or the test command which doubles as the [ command, rather than the [[ construct which appeared in ksh (thanks Stéphane Chazelas for the tip) and is also used for example in bash, zsh and some other shells.



In most languages, like C, when a clause is already known to be true or false, there's no need to evaluate the remainder parts depending on the operation: if true not after a logical or following it, if false not after a logical and, etc. This of course allows for example to stop when a pointer is NULL and not try to dereference it in the next clause.



But sh's [ expr1 -o expr2 ] construct (including bash's implementation) doesn't do this: it always evaluates both sides, when one would want only expr1 to be evaluated. This might have been done for compatibility with the test command implementation. On the other hand, sh's || and && do follow the usual principle: not evaluated if it won't change the result.



So the difference to note would be:



: > /tmp/effect #clear effect
if [ 1 -eq 1 -o $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect


which yields:



true
or-was-evaluated


Above, each [ could have been replaced with /usr/bin/[ which is an alias to the test command, used before [ was made built-in to shells.



While the two next constructs:



: > /tmp/effect #clear effect
if [ 1 -eq 1 ] || [ $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect


or



: > /tmp/effect #clear effect
if [[ 1 -eq 1 || $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]]; then
echo true;
fi
cat /tmp/effect


Will only yield true and leave effect empty: || behaves correctly, and [[ corrected this issue too.




UPDATE:



As @StéphaneChazelas commented, I missed several differences related to the initial question. I'll just put here the most important one (at least to me): priority of operators.



While the shell will not considere precedence:



if true || true && false; then
echo true
else
echo false
fi


yields (because there is no precedence and thus first true || true is evaluated, and then && false):



false


inside [[ ]] the && operator has precedence over ||:



if [[ 1 -eq 1 || 1 -eq 1 && 1 -eq 0 ]]; then
echo true
else
echo false
fi


yields (because 1 -eq 1 && 1 -eq 0 is grouped and is thus the 2nd member of ||):



true


at least for ksh, bash, zsh.



So [[ ]] has improved behaviour over both [ ] and direct shell logical operators.







share|improve this answer














share|improve this answer



share|improve this answer








edited Jul 5 at 14:56

























answered Jul 5 at 11:12









A.BA.B

7,8401 gold badge14 silver badges36 bronze badges




7,8401 gold badge14 silver badges36 bronze badges







  • 1





    [ x -o y ] doesn't have to evaluate both side. While GNU test or the [ builtin of bash do, you'd find with strace zsh -c '[ x -o -f /x ]' that [ doesn't try to stat() /x. Same with mksh. But it's true that -o and -a are severely broken, can't be used reliably and are deprecated by POSIX.

    – Stéphane Chazelas
    Jul 5 at 11:20







  • 1





    One difference is that inside [[...]], && has higher precedence than ||, while outside they have equal precedence. Compare ksh -c '[[ x || x && "" ]]' vs sh -c 'true || true && false'

    – Stéphane Chazelas
    Jul 5 at 11:24






  • 1





    Note that the standard [ / test utility doesn't have a == operator. The equality operator is = (note that inside ksh's [[...]], =/== are not equality operators, but pattern matching ones).

    – Stéphane Chazelas
    Jul 5 at 11:26






  • 1





    It's the other way round. && has precedence over || inside [[...]] (or ((...))) but not the && and || shell operators. [[ x || y && z ]] is x || (y && z) while x || y && z is (x || y) && z (operators evaluated left to right without precedence). Similar to how * has precedence over + (1 + 2 * 3 is 1 + (2 * 3)) but + and - have same precedence.

    – Stéphane Chazelas
    Jul 5 at 13:04







  • 1





    If && has precedence over ||, then it should be true || (true && false), instead of (true || true) && false

    – Prvt_Yadv
    Jul 5 at 13:11












  • 1





    [ x -o y ] doesn't have to evaluate both side. While GNU test or the [ builtin of bash do, you'd find with strace zsh -c '[ x -o -f /x ]' that [ doesn't try to stat() /x. Same with mksh. But it's true that -o and -a are severely broken, can't be used reliably and are deprecated by POSIX.

    – Stéphane Chazelas
    Jul 5 at 11:20







  • 1





    One difference is that inside [[...]], && has higher precedence than ||, while outside they have equal precedence. Compare ksh -c '[[ x || x && "" ]]' vs sh -c 'true || true && false'

    – Stéphane Chazelas
    Jul 5 at 11:24






  • 1





    Note that the standard [ / test utility doesn't have a == operator. The equality operator is = (note that inside ksh's [[...]], =/== are not equality operators, but pattern matching ones).

    – Stéphane Chazelas
    Jul 5 at 11:26






  • 1





    It's the other way round. && has precedence over || inside [[...]] (or ((...))) but not the && and || shell operators. [[ x || y && z ]] is x || (y && z) while x || y && z is (x || y) && z (operators evaluated left to right without precedence). Similar to how * has precedence over + (1 + 2 * 3 is 1 + (2 * 3)) but + and - have same precedence.

    – Stéphane Chazelas
    Jul 5 at 13:04







  • 1





    If && has precedence over ||, then it should be true || (true && false), instead of (true || true) && false

    – Prvt_Yadv
    Jul 5 at 13:11







1




1





[ x -o y ] doesn't have to evaluate both side. While GNU test or the [ builtin of bash do, you'd find with strace zsh -c '[ x -o -f /x ]' that [ doesn't try to stat() /x. Same with mksh. But it's true that -o and -a are severely broken, can't be used reliably and are deprecated by POSIX.

– Stéphane Chazelas
Jul 5 at 11:20






[ x -o y ] doesn't have to evaluate both side. While GNU test or the [ builtin of bash do, you'd find with strace zsh -c '[ x -o -f /x ]' that [ doesn't try to stat() /x. Same with mksh. But it's true that -o and -a are severely broken, can't be used reliably and are deprecated by POSIX.

– Stéphane Chazelas
Jul 5 at 11:20





1




1





One difference is that inside [[...]], && has higher precedence than ||, while outside they have equal precedence. Compare ksh -c '[[ x || x && "" ]]' vs sh -c 'true || true && false'

– Stéphane Chazelas
Jul 5 at 11:24





One difference is that inside [[...]], && has higher precedence than ||, while outside they have equal precedence. Compare ksh -c '[[ x || x && "" ]]' vs sh -c 'true || true && false'

– Stéphane Chazelas
Jul 5 at 11:24




1




1





Note that the standard [ / test utility doesn't have a == operator. The equality operator is = (note that inside ksh's [[...]], =/== are not equality operators, but pattern matching ones).

– Stéphane Chazelas
Jul 5 at 11:26





Note that the standard [ / test utility doesn't have a == operator. The equality operator is = (note that inside ksh's [[...]], =/== are not equality operators, but pattern matching ones).

– Stéphane Chazelas
Jul 5 at 11:26




1




1





It's the other way round. && has precedence over || inside [[...]] (or ((...))) but not the && and || shell operators. [[ x || y && z ]] is x || (y && z) while x || y && z is (x || y) && z (operators evaluated left to right without precedence). Similar to how * has precedence over + (1 + 2 * 3 is 1 + (2 * 3)) but + and - have same precedence.

– Stéphane Chazelas
Jul 5 at 13:04






It's the other way round. && has precedence over || inside [[...]] (or ((...))) but not the && and || shell operators. [[ x || y && z ]] is x || (y && z) while x || y && z is (x || y) && z (operators evaluated left to right without precedence). Similar to how * has precedence over + (1 + 2 * 3 is 1 + (2 * 3)) but + and - have same precedence.

– Stéphane Chazelas
Jul 5 at 13:04





1




1





If && has precedence over ||, then it should be true || (true && false), instead of (true || true) && false

– Prvt_Yadv
Jul 5 at 13:11





If && has precedence over ||, then it should be true || (true && false), instead of (true || true) && false

– Prvt_Yadv
Jul 5 at 13:11

















draft saved

draft discarded
















































Thanks for contributing an answer to Unix & Linux Stack Exchange!


  • 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%2funix.stackexchange.com%2fquestions%2f528505%2fdifference-between-expr1-expr2-and-expr1-expr2%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

Get product attribute by attribute group code in magento 2get product attribute by product attribute group in magento 2Magento 2 Log Bundle Product Data in List Page?How to get all product attribute of a attribute group of Default attribute set?Magento 2.1 Create a filter in the product grid by new attributeMagento 2 : Get Product Attribute values By GroupMagento 2 How to get all existing values for one attributeMagento 2 get custom attribute of a single product inside a pluginMagento 2.3 How to get all the Multi Source Inventory (MSI) locations collection in custom module?Magento2: how to develop rest API to get new productsGet product attribute by attribute group code ( [attribute_group_code] ) in magento 2

Category:9 (number) SubcategoriesMedia in category "9 (number)"Navigation menuUpload mediaGND ID: 4485639-8Library of Congress authority ID: sh85091979ReasonatorScholiaStatistics

Magento 2.3: How do i solve this, Not registered handle, on custom form?How can i rewrite TierPrice Block in Magento2magento 2 captcha not rendering if I override layout xmlmain.CRITICAL: Plugin class doesn't existMagento 2 : Problem while adding custom button order view page?Magento 2.2.5: Overriding Admin Controller sales/orderMagento 2.2.5: Add, Update and Delete existing products Custom OptionsMagento 2.3 : File Upload issue in UI Component FormMagento2 Not registered handleHow to configured Form Builder Js in my custom magento 2.3.0 module?Magento 2.3. How to create image upload field in an admin form