Precedence of the shell logical operators &&, ||
I am trying to understand how the logical operator precedence works in bash. For example, I would have expected, that the following command does not echo anything.
true || echo aaa && echo bbb
However, contrary to my expectation, bbb
gets printed.
Can somebody please explain, how can I make sense of compounded &&
and ||
operators in bash?
bash shell precedence
add a comment |
I am trying to understand how the logical operator precedence works in bash. For example, I would have expected, that the following command does not echo anything.
true || echo aaa && echo bbb
However, contrary to my expectation, bbb
gets printed.
Can somebody please explain, how can I make sense of compounded &&
and ||
operators in bash?
bash shell precedence
add a comment |
I am trying to understand how the logical operator precedence works in bash. For example, I would have expected, that the following command does not echo anything.
true || echo aaa && echo bbb
However, contrary to my expectation, bbb
gets printed.
Can somebody please explain, how can I make sense of compounded &&
and ||
operators in bash?
bash shell precedence
I am trying to understand how the logical operator precedence works in bash. For example, I would have expected, that the following command does not echo anything.
true || echo aaa && echo bbb
However, contrary to my expectation, bbb
gets printed.
Can somebody please explain, how can I make sense of compounded &&
and ||
operators in bash?
bash shell precedence
bash shell precedence
edited 43 mins ago
codeforester
376317
376317
asked Aug 30 '13 at 11:16
Martin VegterMartin Vegter
28437126241
28437126241
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
In many computer languages, operators with the same precedence are left-associative. That is, in the absence of grouping structures, leftmost operations are executed first. Bash is no exception to this rule.
This is important because, in Bash, &&
and ||
have the same precedence.
So what happens in your example is that the leftmost operation (||
) is carried out first:
true || echo aaa
Since true
is obviously true, the ||
operator short-circuits and the whole statement is considered true without the need to evaluate echo aaa
as you would expect. Now it remains to do the rightmost operation:
(...) && echo bbb
Since the first operation evaluated to true (i.e. had a 0 exit status), it's as if you're executing
true && echo bbb
so the &&
will not short-circuit, which is why you see bbb
echoed.
You would get the same behavior with
false && echo aaa || echo bbb
Notes based on the comments
- You should note that the left-associativity rule is only followed when both operators have the same precedence. This is not the case when you use these operators in conjunction with keywords such as
[[...]]
or((...))
or use the-o
and-a
operators as arguments to thetest
or[
commands. In such cases, AND (&&
or-a
) takes precedence over OR (||
or-o
). Thanks to Stephane Chazelas' comment for clarifying this point.
It seems that in C and C-like languages
&&
has higher precedence than||
which is probably why you expected your original construct to behave like
true || (echo aaa && echo bbb).
This is not the case with Bash, however, in which both operators have the same precedence, which is why Bash parses your expression using the left-associativity rule. Thanks to Kevin's comment for bringing this up.
There might also be cases where all 3 expressions are evaluated. If the first command returns a non-zero exit status, the
||
won't short circuit and goes on to execute the second command. If the second command returns with a zero exit status, then the&&
won't short-circuit as well and the third command will be executed. Thanks to Ignacio Vazquez-Abrams' comment for bringing this up.
25
A wee note to add a little more confusion: while the&&
and||
shell operators as incmd1 && cmd2 || cmd3
have same precedence, the&&
in((...))
and[[...]]
has precedence over||
(((a || b && c))
is((a || (b && c)))
). Same goes for-a
/-o
intest
/[
andfind
and&
/|
inexpr
.
– Stéphane Chazelas
Aug 30 '13 at 12:17
14
In c-like languages,&&
has higher precedence than||
, so the OP's expected behavior would happen. Unwary users used to such languages may not realize that in bash they have the same precedence, so it may be worth pointing out more explicitly that they do have the same precedence in bash.
– Kevin
Aug 30 '13 at 13:06
Also note that there are situations where all three commands can be run, i.e. if the middle command can return either true or false.
– Ignacio Vazquez-Abrams
Aug 30 '13 at 13:42
@Kevin Please check edited answer.
– Joseph R.
Aug 30 '13 at 18:51
1
Today, for me, the top Google hit for "bash operator precedence" is tldp.org/LDP/abs/html/opprecedence.html... which claims that && has a higher precedence than ||. Yet @JosephR. is clearly right de facto and de jure too. Dash behaves the same and searching for "precedence" in pubs.opengroup.org/onlinepubs/009695399/utilities/…, I see it's a POSIX requirement, so we can depend on it. All I found for bug reporting was the author's email address, which has surely been spammed to death in the last six years. I'll try anyway...
– Martin Dorey
Aug 21 '18 at 19:37
|
show 2 more comments
If you want multiple things to depend on your condition, group them:
true || { echo aaa && echo bbb; }
That prints nothing, while
true && { echo aaa && echo bbb; }
prints both strings.
The reason this happens is a lot more simple than Joseph is making out. Remember what Bash does with ||
and &&
. It's all about the previous command's return status. A literal way of looking at your raw command is:
( true || echo aaa ) && echo bbb
The first command (true || echo aaa
) is exiting with 0
.
$ true || echo aaa; echo $?
0
$ true && echo aaa; echo $?
aaa
0
$ false && echo aaa; echo $?
1
$ false || echo aaa; echo $?
aaa
0
6
+1 For achieving the OP's intended outcome. Note that the parentheses you placed in(true || echo aaa) && echo bbb
is exactly what I'm making out.
– Joseph R.
Aug 30 '13 at 13:53
1
Nice to see @Oli in this side of the world.
– Braiam
Aug 30 '13 at 16:12
7
Note the semi-column;
at the very end. Without this, it will not work!
– Serge Stroobandt
Dec 19 '16 at 2:46
2
I was running into trouble with this because I was missing the trailing semi-colon after the last command (e.g.echo bbb;
in the first examples). Once I figured out I was missing that, this answer was exactly what I was looking for. +1 for helping me figure out how to accomplish what I wanted!
– Doktor J
Jun 12 '17 at 18:03
5
Worth reading for anyone confused by(...)
and{...}
notation: command grouping manual
– ANTARA
Jun 4 '18 at 14:57
|
show 2 more comments
The &&
and ||
operators are not exact inline replacements for if-then-else. Though if used carefully, they can accomplish much the same thing.
A single test is straightforward and unambiguous...
[[ A == A ]] && echo TRUE # TRUE
[[ A == B ]] && echo TRUE #
[[ A == A ]] || echo FALSE #
[[ A == B ]] || echo FALSE # FALSE
However, attempting to add multiple tests may yield unexpected results...
[[ A == A ]] && echo TRUE || echo FALSE # TRUE (as expected)
[[ A == B ]] && echo TRUE || echo FALSE # FALSE (as expected)
[[ A == A ]] || echo FALSE && echo TRUE # TRUE (as expected)
[[ A == B ]] || echo FALSE && echo TRUE # FALSE TRUE (huh?)
Why are both FALSE and TRUE echoed?
What's happening here is that we've not realized that &&
and ||
are overloaded operators that act differently inside conditional test brackets [[ ]]
than they do in the AND and OR (conditional execution) list we have here.
From the bash manpage (edited)...
Lists
A list is a sequence of one or more pipelines separated by one of the
operators ;, &, &&, or ││, and optionally terminated by one of ;, &,
or . Of these list operators, && and ││ have equal
precedence, followed by ; and &, which have equal precedence.
A sequence of one or more newlines may appear in a list instead of a
semicolon to delimit commands.
If a command is terminated by the control operator &, the shell
executes the command in the background in a subshell. The shell does
not wait for the command to finish, and the return status is 0.
Commands separated by a ; are executed sequentially; the shell waits
for each command to terminate in turn. The return status is the exit
status of the last command executed.
AND and OR lists are sequences of one of more pipelines separated by
the && and ││ control operators, respectively. AND and OR lists are
executed with left associativity.
An AND list has the form ...
command1 && command2
Command2 is executed if, and only if, command1 returns an exit status of zero.
An OR list has the form ...
command1 ││ command2
Command2 is executed if and only if command1 returns a non-zero exit status.
The return status of AND and OR lists
is the exit status of the last command executed in the list.
Returning to our last example...
[[ A == B ]] || echo FALSE && echo TRUE
[[ A == B ]] is false
|| Does NOT mean OR! It means...
'execute next command if last command return code(rc) was false'
echo FALSE The 'echo' command rc is always true
(i.e. it successfully echoed the word "FALSE")
&& Execute next command if last command rc was true
echo TRUE Since the 'echo FALSE' rc was true, then echo "TRUE"
Okay. If that's correct, then why does the next to last example echo anything at all?
[[ A == A ]] || echo FALSE && echo TRUE
[[ A == A ]] is true
|| execute next command if last command rc was false.
echo FALSE Since last rc was true, shouldn't it have stopped before this?
Nope. Instead, it skips the 'echo FALSE', does not even try to
execute it, and continues looking for a `&&` clause.
&& ... which it finds here
echo TRUE ... so, since `[[ A == A ]]` is true, then it echos "TRUE"
The risk of logic errors when using more than one &&
or ||
in a command list is quite high.
Recommendations
A single &&
or ||
in a command list works as expected so is pretty safe. If it's a situation where you don't need an else clause, something like the following can be clearer to follow (the curly braces are required to group the last 2 commands) ...
[[ $1 == --help ]] && { echo "$HELP"; exit; }
Multiple &&
and ||
operators, where each command except for the last is a test (i.e. inside brackets [[ ]]
), are usually also safe as all but the last operator behave as expected. The last operator acts more like a then
or else
clause.
add a comment |
I also got confused by this but here's how I think about the way Bash reads your statement (as it reads the symbols left to right):
- Found symbol
true
. This will need to be evaluated once the end of the command is reached. At this point, don't know if it has any arguments. Store command in execution buffer. - Found symbol
||
. Previous command is now complete, so evaluate it. Command (buffer) being executed:true
. Result of evaluation: 0 (i.e. success). Store result 0 in "last evaluation" register. Now consider symbol||
itself. This depends on the result of the last evaluation being non-zero. Checked "last evaluation" register and found 0. Since 0 is not non-zero, the following command does not need to be evaluated. - Found symbol
echo
. Can ignore this symbol, because the following command did not need to be evaluated. - Found symbol
aaa
. This is an argument to commandecho
(3), but sinceecho
(3) did not need to be evaluated, it can be ignored. - Found symbol
&&
. This depends on the result of the last evaluation being zero. Checked "last evaluation" register and found 0. Since 0 is zero, the following command does need to be evaluated. - Found symbol
echo
. This command needs to be evaluated once the end of the command is reached, because the following command did need to be evaluated. Store command in execution buffer. - Found symbol
bbb
. This is an argument to commandecho
(6). Sinceecho
did need to be evaluated, addbbb
to execution buffer. - Reached end of line. Previous command is now complete and did need to be evaluated. Command (buffer) being executed:
echo bbb
. Result of evaluation: 0 (i.e. success). Store result 0 in "last evaluation" register.
And of course, the last step causes bbb
to be echoed to the console.
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f88850%2fprecedence-of-the-shell-logical-operators%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
In many computer languages, operators with the same precedence are left-associative. That is, in the absence of grouping structures, leftmost operations are executed first. Bash is no exception to this rule.
This is important because, in Bash, &&
and ||
have the same precedence.
So what happens in your example is that the leftmost operation (||
) is carried out first:
true || echo aaa
Since true
is obviously true, the ||
operator short-circuits and the whole statement is considered true without the need to evaluate echo aaa
as you would expect. Now it remains to do the rightmost operation:
(...) && echo bbb
Since the first operation evaluated to true (i.e. had a 0 exit status), it's as if you're executing
true && echo bbb
so the &&
will not short-circuit, which is why you see bbb
echoed.
You would get the same behavior with
false && echo aaa || echo bbb
Notes based on the comments
- You should note that the left-associativity rule is only followed when both operators have the same precedence. This is not the case when you use these operators in conjunction with keywords such as
[[...]]
or((...))
or use the-o
and-a
operators as arguments to thetest
or[
commands. In such cases, AND (&&
or-a
) takes precedence over OR (||
or-o
). Thanks to Stephane Chazelas' comment for clarifying this point.
It seems that in C and C-like languages
&&
has higher precedence than||
which is probably why you expected your original construct to behave like
true || (echo aaa && echo bbb).
This is not the case with Bash, however, in which both operators have the same precedence, which is why Bash parses your expression using the left-associativity rule. Thanks to Kevin's comment for bringing this up.
There might also be cases where all 3 expressions are evaluated. If the first command returns a non-zero exit status, the
||
won't short circuit and goes on to execute the second command. If the second command returns with a zero exit status, then the&&
won't short-circuit as well and the third command will be executed. Thanks to Ignacio Vazquez-Abrams' comment for bringing this up.
25
A wee note to add a little more confusion: while the&&
and||
shell operators as incmd1 && cmd2 || cmd3
have same precedence, the&&
in((...))
and[[...]]
has precedence over||
(((a || b && c))
is((a || (b && c)))
). Same goes for-a
/-o
intest
/[
andfind
and&
/|
inexpr
.
– Stéphane Chazelas
Aug 30 '13 at 12:17
14
In c-like languages,&&
has higher precedence than||
, so the OP's expected behavior would happen. Unwary users used to such languages may not realize that in bash they have the same precedence, so it may be worth pointing out more explicitly that they do have the same precedence in bash.
– Kevin
Aug 30 '13 at 13:06
Also note that there are situations where all three commands can be run, i.e. if the middle command can return either true or false.
– Ignacio Vazquez-Abrams
Aug 30 '13 at 13:42
@Kevin Please check edited answer.
– Joseph R.
Aug 30 '13 at 18:51
1
Today, for me, the top Google hit for "bash operator precedence" is tldp.org/LDP/abs/html/opprecedence.html... which claims that && has a higher precedence than ||. Yet @JosephR. is clearly right de facto and de jure too. Dash behaves the same and searching for "precedence" in pubs.opengroup.org/onlinepubs/009695399/utilities/…, I see it's a POSIX requirement, so we can depend on it. All I found for bug reporting was the author's email address, which has surely been spammed to death in the last six years. I'll try anyway...
– Martin Dorey
Aug 21 '18 at 19:37
|
show 2 more comments
In many computer languages, operators with the same precedence are left-associative. That is, in the absence of grouping structures, leftmost operations are executed first. Bash is no exception to this rule.
This is important because, in Bash, &&
and ||
have the same precedence.
So what happens in your example is that the leftmost operation (||
) is carried out first:
true || echo aaa
Since true
is obviously true, the ||
operator short-circuits and the whole statement is considered true without the need to evaluate echo aaa
as you would expect. Now it remains to do the rightmost operation:
(...) && echo bbb
Since the first operation evaluated to true (i.e. had a 0 exit status), it's as if you're executing
true && echo bbb
so the &&
will not short-circuit, which is why you see bbb
echoed.
You would get the same behavior with
false && echo aaa || echo bbb
Notes based on the comments
- You should note that the left-associativity rule is only followed when both operators have the same precedence. This is not the case when you use these operators in conjunction with keywords such as
[[...]]
or((...))
or use the-o
and-a
operators as arguments to thetest
or[
commands. In such cases, AND (&&
or-a
) takes precedence over OR (||
or-o
). Thanks to Stephane Chazelas' comment for clarifying this point.
It seems that in C and C-like languages
&&
has higher precedence than||
which is probably why you expected your original construct to behave like
true || (echo aaa && echo bbb).
This is not the case with Bash, however, in which both operators have the same precedence, which is why Bash parses your expression using the left-associativity rule. Thanks to Kevin's comment for bringing this up.
There might also be cases where all 3 expressions are evaluated. If the first command returns a non-zero exit status, the
||
won't short circuit and goes on to execute the second command. If the second command returns with a zero exit status, then the&&
won't short-circuit as well and the third command will be executed. Thanks to Ignacio Vazquez-Abrams' comment for bringing this up.
25
A wee note to add a little more confusion: while the&&
and||
shell operators as incmd1 && cmd2 || cmd3
have same precedence, the&&
in((...))
and[[...]]
has precedence over||
(((a || b && c))
is((a || (b && c)))
). Same goes for-a
/-o
intest
/[
andfind
and&
/|
inexpr
.
– Stéphane Chazelas
Aug 30 '13 at 12:17
14
In c-like languages,&&
has higher precedence than||
, so the OP's expected behavior would happen. Unwary users used to such languages may not realize that in bash they have the same precedence, so it may be worth pointing out more explicitly that they do have the same precedence in bash.
– Kevin
Aug 30 '13 at 13:06
Also note that there are situations where all three commands can be run, i.e. if the middle command can return either true or false.
– Ignacio Vazquez-Abrams
Aug 30 '13 at 13:42
@Kevin Please check edited answer.
– Joseph R.
Aug 30 '13 at 18:51
1
Today, for me, the top Google hit for "bash operator precedence" is tldp.org/LDP/abs/html/opprecedence.html... which claims that && has a higher precedence than ||. Yet @JosephR. is clearly right de facto and de jure too. Dash behaves the same and searching for "precedence" in pubs.opengroup.org/onlinepubs/009695399/utilities/…, I see it's a POSIX requirement, so we can depend on it. All I found for bug reporting was the author's email address, which has surely been spammed to death in the last six years. I'll try anyway...
– Martin Dorey
Aug 21 '18 at 19:37
|
show 2 more comments
In many computer languages, operators with the same precedence are left-associative. That is, in the absence of grouping structures, leftmost operations are executed first. Bash is no exception to this rule.
This is important because, in Bash, &&
and ||
have the same precedence.
So what happens in your example is that the leftmost operation (||
) is carried out first:
true || echo aaa
Since true
is obviously true, the ||
operator short-circuits and the whole statement is considered true without the need to evaluate echo aaa
as you would expect. Now it remains to do the rightmost operation:
(...) && echo bbb
Since the first operation evaluated to true (i.e. had a 0 exit status), it's as if you're executing
true && echo bbb
so the &&
will not short-circuit, which is why you see bbb
echoed.
You would get the same behavior with
false && echo aaa || echo bbb
Notes based on the comments
- You should note that the left-associativity rule is only followed when both operators have the same precedence. This is not the case when you use these operators in conjunction with keywords such as
[[...]]
or((...))
or use the-o
and-a
operators as arguments to thetest
or[
commands. In such cases, AND (&&
or-a
) takes precedence over OR (||
or-o
). Thanks to Stephane Chazelas' comment for clarifying this point.
It seems that in C and C-like languages
&&
has higher precedence than||
which is probably why you expected your original construct to behave like
true || (echo aaa && echo bbb).
This is not the case with Bash, however, in which both operators have the same precedence, which is why Bash parses your expression using the left-associativity rule. Thanks to Kevin's comment for bringing this up.
There might also be cases where all 3 expressions are evaluated. If the first command returns a non-zero exit status, the
||
won't short circuit and goes on to execute the second command. If the second command returns with a zero exit status, then the&&
won't short-circuit as well and the third command will be executed. Thanks to Ignacio Vazquez-Abrams' comment for bringing this up.
In many computer languages, operators with the same precedence are left-associative. That is, in the absence of grouping structures, leftmost operations are executed first. Bash is no exception to this rule.
This is important because, in Bash, &&
and ||
have the same precedence.
So what happens in your example is that the leftmost operation (||
) is carried out first:
true || echo aaa
Since true
is obviously true, the ||
operator short-circuits and the whole statement is considered true without the need to evaluate echo aaa
as you would expect. Now it remains to do the rightmost operation:
(...) && echo bbb
Since the first operation evaluated to true (i.e. had a 0 exit status), it's as if you're executing
true && echo bbb
so the &&
will not short-circuit, which is why you see bbb
echoed.
You would get the same behavior with
false && echo aaa || echo bbb
Notes based on the comments
- You should note that the left-associativity rule is only followed when both operators have the same precedence. This is not the case when you use these operators in conjunction with keywords such as
[[...]]
or((...))
or use the-o
and-a
operators as arguments to thetest
or[
commands. In such cases, AND (&&
or-a
) takes precedence over OR (||
or-o
). Thanks to Stephane Chazelas' comment for clarifying this point.
It seems that in C and C-like languages
&&
has higher precedence than||
which is probably why you expected your original construct to behave like
true || (echo aaa && echo bbb).
This is not the case with Bash, however, in which both operators have the same precedence, which is why Bash parses your expression using the left-associativity rule. Thanks to Kevin's comment for bringing this up.
There might also be cases where all 3 expressions are evaluated. If the first command returns a non-zero exit status, the
||
won't short circuit and goes on to execute the second command. If the second command returns with a zero exit status, then the&&
won't short-circuit as well and the third command will be executed. Thanks to Ignacio Vazquez-Abrams' comment for bringing this up.
edited Sep 1 '13 at 15:23
answered Aug 30 '13 at 11:26
Joseph R.Joseph R.
28.5k375116
28.5k375116
25
A wee note to add a little more confusion: while the&&
and||
shell operators as incmd1 && cmd2 || cmd3
have same precedence, the&&
in((...))
and[[...]]
has precedence over||
(((a || b && c))
is((a || (b && c)))
). Same goes for-a
/-o
intest
/[
andfind
and&
/|
inexpr
.
– Stéphane Chazelas
Aug 30 '13 at 12:17
14
In c-like languages,&&
has higher precedence than||
, so the OP's expected behavior would happen. Unwary users used to such languages may not realize that in bash they have the same precedence, so it may be worth pointing out more explicitly that they do have the same precedence in bash.
– Kevin
Aug 30 '13 at 13:06
Also note that there are situations where all three commands can be run, i.e. if the middle command can return either true or false.
– Ignacio Vazquez-Abrams
Aug 30 '13 at 13:42
@Kevin Please check edited answer.
– Joseph R.
Aug 30 '13 at 18:51
1
Today, for me, the top Google hit for "bash operator precedence" is tldp.org/LDP/abs/html/opprecedence.html... which claims that && has a higher precedence than ||. Yet @JosephR. is clearly right de facto and de jure too. Dash behaves the same and searching for "precedence" in pubs.opengroup.org/onlinepubs/009695399/utilities/…, I see it's a POSIX requirement, so we can depend on it. All I found for bug reporting was the author's email address, which has surely been spammed to death in the last six years. I'll try anyway...
– Martin Dorey
Aug 21 '18 at 19:37
|
show 2 more comments
25
A wee note to add a little more confusion: while the&&
and||
shell operators as incmd1 && cmd2 || cmd3
have same precedence, the&&
in((...))
and[[...]]
has precedence over||
(((a || b && c))
is((a || (b && c)))
). Same goes for-a
/-o
intest
/[
andfind
and&
/|
inexpr
.
– Stéphane Chazelas
Aug 30 '13 at 12:17
14
In c-like languages,&&
has higher precedence than||
, so the OP's expected behavior would happen. Unwary users used to such languages may not realize that in bash they have the same precedence, so it may be worth pointing out more explicitly that they do have the same precedence in bash.
– Kevin
Aug 30 '13 at 13:06
Also note that there are situations where all three commands can be run, i.e. if the middle command can return either true or false.
– Ignacio Vazquez-Abrams
Aug 30 '13 at 13:42
@Kevin Please check edited answer.
– Joseph R.
Aug 30 '13 at 18:51
1
Today, for me, the top Google hit for "bash operator precedence" is tldp.org/LDP/abs/html/opprecedence.html... which claims that && has a higher precedence than ||. Yet @JosephR. is clearly right de facto and de jure too. Dash behaves the same and searching for "precedence" in pubs.opengroup.org/onlinepubs/009695399/utilities/…, I see it's a POSIX requirement, so we can depend on it. All I found for bug reporting was the author's email address, which has surely been spammed to death in the last six years. I'll try anyway...
– Martin Dorey
Aug 21 '18 at 19:37
25
25
A wee note to add a little more confusion: while the
&&
and ||
shell operators as in cmd1 && cmd2 || cmd3
have same precedence, the &&
in ((...))
and [[...]]
has precedence over ||
(((a || b && c))
is ((a || (b && c)))
). Same goes for -a
/-o
in test
/[
and find
and &
/|
in expr
.– Stéphane Chazelas
Aug 30 '13 at 12:17
A wee note to add a little more confusion: while the
&&
and ||
shell operators as in cmd1 && cmd2 || cmd3
have same precedence, the &&
in ((...))
and [[...]]
has precedence over ||
(((a || b && c))
is ((a || (b && c)))
). Same goes for -a
/-o
in test
/[
and find
and &
/|
in expr
.– Stéphane Chazelas
Aug 30 '13 at 12:17
14
14
In c-like languages,
&&
has higher precedence than ||
, so the OP's expected behavior would happen. Unwary users used to such languages may not realize that in bash they have the same precedence, so it may be worth pointing out more explicitly that they do have the same precedence in bash.– Kevin
Aug 30 '13 at 13:06
In c-like languages,
&&
has higher precedence than ||
, so the OP's expected behavior would happen. Unwary users used to such languages may not realize that in bash they have the same precedence, so it may be worth pointing out more explicitly that they do have the same precedence in bash.– Kevin
Aug 30 '13 at 13:06
Also note that there are situations where all three commands can be run, i.e. if the middle command can return either true or false.
– Ignacio Vazquez-Abrams
Aug 30 '13 at 13:42
Also note that there are situations where all three commands can be run, i.e. if the middle command can return either true or false.
– Ignacio Vazquez-Abrams
Aug 30 '13 at 13:42
@Kevin Please check edited answer.
– Joseph R.
Aug 30 '13 at 18:51
@Kevin Please check edited answer.
– Joseph R.
Aug 30 '13 at 18:51
1
1
Today, for me, the top Google hit for "bash operator precedence" is tldp.org/LDP/abs/html/opprecedence.html... which claims that && has a higher precedence than ||. Yet @JosephR. is clearly right de facto and de jure too. Dash behaves the same and searching for "precedence" in pubs.opengroup.org/onlinepubs/009695399/utilities/…, I see it's a POSIX requirement, so we can depend on it. All I found for bug reporting was the author's email address, which has surely been spammed to death in the last six years. I'll try anyway...
– Martin Dorey
Aug 21 '18 at 19:37
Today, for me, the top Google hit for "bash operator precedence" is tldp.org/LDP/abs/html/opprecedence.html... which claims that && has a higher precedence than ||. Yet @JosephR. is clearly right de facto and de jure too. Dash behaves the same and searching for "precedence" in pubs.opengroup.org/onlinepubs/009695399/utilities/…, I see it's a POSIX requirement, so we can depend on it. All I found for bug reporting was the author's email address, which has surely been spammed to death in the last six years. I'll try anyway...
– Martin Dorey
Aug 21 '18 at 19:37
|
show 2 more comments
If you want multiple things to depend on your condition, group them:
true || { echo aaa && echo bbb; }
That prints nothing, while
true && { echo aaa && echo bbb; }
prints both strings.
The reason this happens is a lot more simple than Joseph is making out. Remember what Bash does with ||
and &&
. It's all about the previous command's return status. A literal way of looking at your raw command is:
( true || echo aaa ) && echo bbb
The first command (true || echo aaa
) is exiting with 0
.
$ true || echo aaa; echo $?
0
$ true && echo aaa; echo $?
aaa
0
$ false && echo aaa; echo $?
1
$ false || echo aaa; echo $?
aaa
0
6
+1 For achieving the OP's intended outcome. Note that the parentheses you placed in(true || echo aaa) && echo bbb
is exactly what I'm making out.
– Joseph R.
Aug 30 '13 at 13:53
1
Nice to see @Oli in this side of the world.
– Braiam
Aug 30 '13 at 16:12
7
Note the semi-column;
at the very end. Without this, it will not work!
– Serge Stroobandt
Dec 19 '16 at 2:46
2
I was running into trouble with this because I was missing the trailing semi-colon after the last command (e.g.echo bbb;
in the first examples). Once I figured out I was missing that, this answer was exactly what I was looking for. +1 for helping me figure out how to accomplish what I wanted!
– Doktor J
Jun 12 '17 at 18:03
5
Worth reading for anyone confused by(...)
and{...}
notation: command grouping manual
– ANTARA
Jun 4 '18 at 14:57
|
show 2 more comments
If you want multiple things to depend on your condition, group them:
true || { echo aaa && echo bbb; }
That prints nothing, while
true && { echo aaa && echo bbb; }
prints both strings.
The reason this happens is a lot more simple than Joseph is making out. Remember what Bash does with ||
and &&
. It's all about the previous command's return status. A literal way of looking at your raw command is:
( true || echo aaa ) && echo bbb
The first command (true || echo aaa
) is exiting with 0
.
$ true || echo aaa; echo $?
0
$ true && echo aaa; echo $?
aaa
0
$ false && echo aaa; echo $?
1
$ false || echo aaa; echo $?
aaa
0
6
+1 For achieving the OP's intended outcome. Note that the parentheses you placed in(true || echo aaa) && echo bbb
is exactly what I'm making out.
– Joseph R.
Aug 30 '13 at 13:53
1
Nice to see @Oli in this side of the world.
– Braiam
Aug 30 '13 at 16:12
7
Note the semi-column;
at the very end. Without this, it will not work!
– Serge Stroobandt
Dec 19 '16 at 2:46
2
I was running into trouble with this because I was missing the trailing semi-colon after the last command (e.g.echo bbb;
in the first examples). Once I figured out I was missing that, this answer was exactly what I was looking for. +1 for helping me figure out how to accomplish what I wanted!
– Doktor J
Jun 12 '17 at 18:03
5
Worth reading for anyone confused by(...)
and{...}
notation: command grouping manual
– ANTARA
Jun 4 '18 at 14:57
|
show 2 more comments
If you want multiple things to depend on your condition, group them:
true || { echo aaa && echo bbb; }
That prints nothing, while
true && { echo aaa && echo bbb; }
prints both strings.
The reason this happens is a lot more simple than Joseph is making out. Remember what Bash does with ||
and &&
. It's all about the previous command's return status. A literal way of looking at your raw command is:
( true || echo aaa ) && echo bbb
The first command (true || echo aaa
) is exiting with 0
.
$ true || echo aaa; echo $?
0
$ true && echo aaa; echo $?
aaa
0
$ false && echo aaa; echo $?
1
$ false || echo aaa; echo $?
aaa
0
If you want multiple things to depend on your condition, group them:
true || { echo aaa && echo bbb; }
That prints nothing, while
true && { echo aaa && echo bbb; }
prints both strings.
The reason this happens is a lot more simple than Joseph is making out. Remember what Bash does with ||
and &&
. It's all about the previous command's return status. A literal way of looking at your raw command is:
( true || echo aaa ) && echo bbb
The first command (true || echo aaa
) is exiting with 0
.
$ true || echo aaa; echo $?
0
$ true && echo aaa; echo $?
aaa
0
$ false && echo aaa; echo $?
1
$ false || echo aaa; echo $?
aaa
0
edited Nov 12 '18 at 22:56
Avi Flax
1035
1035
answered Aug 30 '13 at 13:27
OliOli
7,68063248
7,68063248
6
+1 For achieving the OP's intended outcome. Note that the parentheses you placed in(true || echo aaa) && echo bbb
is exactly what I'm making out.
– Joseph R.
Aug 30 '13 at 13:53
1
Nice to see @Oli in this side of the world.
– Braiam
Aug 30 '13 at 16:12
7
Note the semi-column;
at the very end. Without this, it will not work!
– Serge Stroobandt
Dec 19 '16 at 2:46
2
I was running into trouble with this because I was missing the trailing semi-colon after the last command (e.g.echo bbb;
in the first examples). Once I figured out I was missing that, this answer was exactly what I was looking for. +1 for helping me figure out how to accomplish what I wanted!
– Doktor J
Jun 12 '17 at 18:03
5
Worth reading for anyone confused by(...)
and{...}
notation: command grouping manual
– ANTARA
Jun 4 '18 at 14:57
|
show 2 more comments
6
+1 For achieving the OP's intended outcome. Note that the parentheses you placed in(true || echo aaa) && echo bbb
is exactly what I'm making out.
– Joseph R.
Aug 30 '13 at 13:53
1
Nice to see @Oli in this side of the world.
– Braiam
Aug 30 '13 at 16:12
7
Note the semi-column;
at the very end. Without this, it will not work!
– Serge Stroobandt
Dec 19 '16 at 2:46
2
I was running into trouble with this because I was missing the trailing semi-colon after the last command (e.g.echo bbb;
in the first examples). Once I figured out I was missing that, this answer was exactly what I was looking for. +1 for helping me figure out how to accomplish what I wanted!
– Doktor J
Jun 12 '17 at 18:03
5
Worth reading for anyone confused by(...)
and{...}
notation: command grouping manual
– ANTARA
Jun 4 '18 at 14:57
6
6
+1 For achieving the OP's intended outcome. Note that the parentheses you placed in
(true || echo aaa) && echo bbb
is exactly what I'm making out.– Joseph R.
Aug 30 '13 at 13:53
+1 For achieving the OP's intended outcome. Note that the parentheses you placed in
(true || echo aaa) && echo bbb
is exactly what I'm making out.– Joseph R.
Aug 30 '13 at 13:53
1
1
Nice to see @Oli in this side of the world.
– Braiam
Aug 30 '13 at 16:12
Nice to see @Oli in this side of the world.
– Braiam
Aug 30 '13 at 16:12
7
7
Note the semi-column
;
at the very end. Without this, it will not work!– Serge Stroobandt
Dec 19 '16 at 2:46
Note the semi-column
;
at the very end. Without this, it will not work!– Serge Stroobandt
Dec 19 '16 at 2:46
2
2
I was running into trouble with this because I was missing the trailing semi-colon after the last command (e.g.
echo bbb;
in the first examples). Once I figured out I was missing that, this answer was exactly what I was looking for. +1 for helping me figure out how to accomplish what I wanted!– Doktor J
Jun 12 '17 at 18:03
I was running into trouble with this because I was missing the trailing semi-colon after the last command (e.g.
echo bbb;
in the first examples). Once I figured out I was missing that, this answer was exactly what I was looking for. +1 for helping me figure out how to accomplish what I wanted!– Doktor J
Jun 12 '17 at 18:03
5
5
Worth reading for anyone confused by
(...)
and {...}
notation: command grouping manual– ANTARA
Jun 4 '18 at 14:57
Worth reading for anyone confused by
(...)
and {...}
notation: command grouping manual– ANTARA
Jun 4 '18 at 14:57
|
show 2 more comments
The &&
and ||
operators are not exact inline replacements for if-then-else. Though if used carefully, they can accomplish much the same thing.
A single test is straightforward and unambiguous...
[[ A == A ]] && echo TRUE # TRUE
[[ A == B ]] && echo TRUE #
[[ A == A ]] || echo FALSE #
[[ A == B ]] || echo FALSE # FALSE
However, attempting to add multiple tests may yield unexpected results...
[[ A == A ]] && echo TRUE || echo FALSE # TRUE (as expected)
[[ A == B ]] && echo TRUE || echo FALSE # FALSE (as expected)
[[ A == A ]] || echo FALSE && echo TRUE # TRUE (as expected)
[[ A == B ]] || echo FALSE && echo TRUE # FALSE TRUE (huh?)
Why are both FALSE and TRUE echoed?
What's happening here is that we've not realized that &&
and ||
are overloaded operators that act differently inside conditional test brackets [[ ]]
than they do in the AND and OR (conditional execution) list we have here.
From the bash manpage (edited)...
Lists
A list is a sequence of one or more pipelines separated by one of the
operators ;, &, &&, or ││, and optionally terminated by one of ;, &,
or . Of these list operators, && and ││ have equal
precedence, followed by ; and &, which have equal precedence.
A sequence of one or more newlines may appear in a list instead of a
semicolon to delimit commands.
If a command is terminated by the control operator &, the shell
executes the command in the background in a subshell. The shell does
not wait for the command to finish, and the return status is 0.
Commands separated by a ; are executed sequentially; the shell waits
for each command to terminate in turn. The return status is the exit
status of the last command executed.
AND and OR lists are sequences of one of more pipelines separated by
the && and ││ control operators, respectively. AND and OR lists are
executed with left associativity.
An AND list has the form ...
command1 && command2
Command2 is executed if, and only if, command1 returns an exit status of zero.
An OR list has the form ...
command1 ││ command2
Command2 is executed if and only if command1 returns a non-zero exit status.
The return status of AND and OR lists
is the exit status of the last command executed in the list.
Returning to our last example...
[[ A == B ]] || echo FALSE && echo TRUE
[[ A == B ]] is false
|| Does NOT mean OR! It means...
'execute next command if last command return code(rc) was false'
echo FALSE The 'echo' command rc is always true
(i.e. it successfully echoed the word "FALSE")
&& Execute next command if last command rc was true
echo TRUE Since the 'echo FALSE' rc was true, then echo "TRUE"
Okay. If that's correct, then why does the next to last example echo anything at all?
[[ A == A ]] || echo FALSE && echo TRUE
[[ A == A ]] is true
|| execute next command if last command rc was false.
echo FALSE Since last rc was true, shouldn't it have stopped before this?
Nope. Instead, it skips the 'echo FALSE', does not even try to
execute it, and continues looking for a `&&` clause.
&& ... which it finds here
echo TRUE ... so, since `[[ A == A ]]` is true, then it echos "TRUE"
The risk of logic errors when using more than one &&
or ||
in a command list is quite high.
Recommendations
A single &&
or ||
in a command list works as expected so is pretty safe. If it's a situation where you don't need an else clause, something like the following can be clearer to follow (the curly braces are required to group the last 2 commands) ...
[[ $1 == --help ]] && { echo "$HELP"; exit; }
Multiple &&
and ||
operators, where each command except for the last is a test (i.e. inside brackets [[ ]]
), are usually also safe as all but the last operator behave as expected. The last operator acts more like a then
or else
clause.
add a comment |
The &&
and ||
operators are not exact inline replacements for if-then-else. Though if used carefully, they can accomplish much the same thing.
A single test is straightforward and unambiguous...
[[ A == A ]] && echo TRUE # TRUE
[[ A == B ]] && echo TRUE #
[[ A == A ]] || echo FALSE #
[[ A == B ]] || echo FALSE # FALSE
However, attempting to add multiple tests may yield unexpected results...
[[ A == A ]] && echo TRUE || echo FALSE # TRUE (as expected)
[[ A == B ]] && echo TRUE || echo FALSE # FALSE (as expected)
[[ A == A ]] || echo FALSE && echo TRUE # TRUE (as expected)
[[ A == B ]] || echo FALSE && echo TRUE # FALSE TRUE (huh?)
Why are both FALSE and TRUE echoed?
What's happening here is that we've not realized that &&
and ||
are overloaded operators that act differently inside conditional test brackets [[ ]]
than they do in the AND and OR (conditional execution) list we have here.
From the bash manpage (edited)...
Lists
A list is a sequence of one or more pipelines separated by one of the
operators ;, &, &&, or ││, and optionally terminated by one of ;, &,
or . Of these list operators, && and ││ have equal
precedence, followed by ; and &, which have equal precedence.
A sequence of one or more newlines may appear in a list instead of a
semicolon to delimit commands.
If a command is terminated by the control operator &, the shell
executes the command in the background in a subshell. The shell does
not wait for the command to finish, and the return status is 0.
Commands separated by a ; are executed sequentially; the shell waits
for each command to terminate in turn. The return status is the exit
status of the last command executed.
AND and OR lists are sequences of one of more pipelines separated by
the && and ││ control operators, respectively. AND and OR lists are
executed with left associativity.
An AND list has the form ...
command1 && command2
Command2 is executed if, and only if, command1 returns an exit status of zero.
An OR list has the form ...
command1 ││ command2
Command2 is executed if and only if command1 returns a non-zero exit status.
The return status of AND and OR lists
is the exit status of the last command executed in the list.
Returning to our last example...
[[ A == B ]] || echo FALSE && echo TRUE
[[ A == B ]] is false
|| Does NOT mean OR! It means...
'execute next command if last command return code(rc) was false'
echo FALSE The 'echo' command rc is always true
(i.e. it successfully echoed the word "FALSE")
&& Execute next command if last command rc was true
echo TRUE Since the 'echo FALSE' rc was true, then echo "TRUE"
Okay. If that's correct, then why does the next to last example echo anything at all?
[[ A == A ]] || echo FALSE && echo TRUE
[[ A == A ]] is true
|| execute next command if last command rc was false.
echo FALSE Since last rc was true, shouldn't it have stopped before this?
Nope. Instead, it skips the 'echo FALSE', does not even try to
execute it, and continues looking for a `&&` clause.
&& ... which it finds here
echo TRUE ... so, since `[[ A == A ]]` is true, then it echos "TRUE"
The risk of logic errors when using more than one &&
or ||
in a command list is quite high.
Recommendations
A single &&
or ||
in a command list works as expected so is pretty safe. If it's a situation where you don't need an else clause, something like the following can be clearer to follow (the curly braces are required to group the last 2 commands) ...
[[ $1 == --help ]] && { echo "$HELP"; exit; }
Multiple &&
and ||
operators, where each command except for the last is a test (i.e. inside brackets [[ ]]
), are usually also safe as all but the last operator behave as expected. The last operator acts more like a then
or else
clause.
add a comment |
The &&
and ||
operators are not exact inline replacements for if-then-else. Though if used carefully, they can accomplish much the same thing.
A single test is straightforward and unambiguous...
[[ A == A ]] && echo TRUE # TRUE
[[ A == B ]] && echo TRUE #
[[ A == A ]] || echo FALSE #
[[ A == B ]] || echo FALSE # FALSE
However, attempting to add multiple tests may yield unexpected results...
[[ A == A ]] && echo TRUE || echo FALSE # TRUE (as expected)
[[ A == B ]] && echo TRUE || echo FALSE # FALSE (as expected)
[[ A == A ]] || echo FALSE && echo TRUE # TRUE (as expected)
[[ A == B ]] || echo FALSE && echo TRUE # FALSE TRUE (huh?)
Why are both FALSE and TRUE echoed?
What's happening here is that we've not realized that &&
and ||
are overloaded operators that act differently inside conditional test brackets [[ ]]
than they do in the AND and OR (conditional execution) list we have here.
From the bash manpage (edited)...
Lists
A list is a sequence of one or more pipelines separated by one of the
operators ;, &, &&, or ││, and optionally terminated by one of ;, &,
or . Of these list operators, && and ││ have equal
precedence, followed by ; and &, which have equal precedence.
A sequence of one or more newlines may appear in a list instead of a
semicolon to delimit commands.
If a command is terminated by the control operator &, the shell
executes the command in the background in a subshell. The shell does
not wait for the command to finish, and the return status is 0.
Commands separated by a ; are executed sequentially; the shell waits
for each command to terminate in turn. The return status is the exit
status of the last command executed.
AND and OR lists are sequences of one of more pipelines separated by
the && and ││ control operators, respectively. AND and OR lists are
executed with left associativity.
An AND list has the form ...
command1 && command2
Command2 is executed if, and only if, command1 returns an exit status of zero.
An OR list has the form ...
command1 ││ command2
Command2 is executed if and only if command1 returns a non-zero exit status.
The return status of AND and OR lists
is the exit status of the last command executed in the list.
Returning to our last example...
[[ A == B ]] || echo FALSE && echo TRUE
[[ A == B ]] is false
|| Does NOT mean OR! It means...
'execute next command if last command return code(rc) was false'
echo FALSE The 'echo' command rc is always true
(i.e. it successfully echoed the word "FALSE")
&& Execute next command if last command rc was true
echo TRUE Since the 'echo FALSE' rc was true, then echo "TRUE"
Okay. If that's correct, then why does the next to last example echo anything at all?
[[ A == A ]] || echo FALSE && echo TRUE
[[ A == A ]] is true
|| execute next command if last command rc was false.
echo FALSE Since last rc was true, shouldn't it have stopped before this?
Nope. Instead, it skips the 'echo FALSE', does not even try to
execute it, and continues looking for a `&&` clause.
&& ... which it finds here
echo TRUE ... so, since `[[ A == A ]]` is true, then it echos "TRUE"
The risk of logic errors when using more than one &&
or ||
in a command list is quite high.
Recommendations
A single &&
or ||
in a command list works as expected so is pretty safe. If it's a situation where you don't need an else clause, something like the following can be clearer to follow (the curly braces are required to group the last 2 commands) ...
[[ $1 == --help ]] && { echo "$HELP"; exit; }
Multiple &&
and ||
operators, where each command except for the last is a test (i.e. inside brackets [[ ]]
), are usually also safe as all but the last operator behave as expected. The last operator acts more like a then
or else
clause.
The &&
and ||
operators are not exact inline replacements for if-then-else. Though if used carefully, they can accomplish much the same thing.
A single test is straightforward and unambiguous...
[[ A == A ]] && echo TRUE # TRUE
[[ A == B ]] && echo TRUE #
[[ A == A ]] || echo FALSE #
[[ A == B ]] || echo FALSE # FALSE
However, attempting to add multiple tests may yield unexpected results...
[[ A == A ]] && echo TRUE || echo FALSE # TRUE (as expected)
[[ A == B ]] && echo TRUE || echo FALSE # FALSE (as expected)
[[ A == A ]] || echo FALSE && echo TRUE # TRUE (as expected)
[[ A == B ]] || echo FALSE && echo TRUE # FALSE TRUE (huh?)
Why are both FALSE and TRUE echoed?
What's happening here is that we've not realized that &&
and ||
are overloaded operators that act differently inside conditional test brackets [[ ]]
than they do in the AND and OR (conditional execution) list we have here.
From the bash manpage (edited)...
Lists
A list is a sequence of one or more pipelines separated by one of the
operators ;, &, &&, or ││, and optionally terminated by one of ;, &,
or . Of these list operators, && and ││ have equal
precedence, followed by ; and &, which have equal precedence.
A sequence of one or more newlines may appear in a list instead of a
semicolon to delimit commands.
If a command is terminated by the control operator &, the shell
executes the command in the background in a subshell. The shell does
not wait for the command to finish, and the return status is 0.
Commands separated by a ; are executed sequentially; the shell waits
for each command to terminate in turn. The return status is the exit
status of the last command executed.
AND and OR lists are sequences of one of more pipelines separated by
the && and ││ control operators, respectively. AND and OR lists are
executed with left associativity.
An AND list has the form ...
command1 && command2
Command2 is executed if, and only if, command1 returns an exit status of zero.
An OR list has the form ...
command1 ││ command2
Command2 is executed if and only if command1 returns a non-zero exit status.
The return status of AND and OR lists
is the exit status of the last command executed in the list.
Returning to our last example...
[[ A == B ]] || echo FALSE && echo TRUE
[[ A == B ]] is false
|| Does NOT mean OR! It means...
'execute next command if last command return code(rc) was false'
echo FALSE The 'echo' command rc is always true
(i.e. it successfully echoed the word "FALSE")
&& Execute next command if last command rc was true
echo TRUE Since the 'echo FALSE' rc was true, then echo "TRUE"
Okay. If that's correct, then why does the next to last example echo anything at all?
[[ A == A ]] || echo FALSE && echo TRUE
[[ A == A ]] is true
|| execute next command if last command rc was false.
echo FALSE Since last rc was true, shouldn't it have stopped before this?
Nope. Instead, it skips the 'echo FALSE', does not even try to
execute it, and continues looking for a `&&` clause.
&& ... which it finds here
echo TRUE ... so, since `[[ A == A ]]` is true, then it echos "TRUE"
The risk of logic errors when using more than one &&
or ||
in a command list is quite high.
Recommendations
A single &&
or ||
in a command list works as expected so is pretty safe. If it's a situation where you don't need an else clause, something like the following can be clearer to follow (the curly braces are required to group the last 2 commands) ...
[[ $1 == --help ]] && { echo "$HELP"; exit; }
Multiple &&
and ||
operators, where each command except for the last is a test (i.e. inside brackets [[ ]]
), are usually also safe as all but the last operator behave as expected. The last operator acts more like a then
or else
clause.
edited Mar 7 '17 at 9:15
answered Sep 6 '13 at 10:35
DocSalvagerDocSalvager
1,32021732
1,32021732
add a comment |
add a comment |
I also got confused by this but here's how I think about the way Bash reads your statement (as it reads the symbols left to right):
- Found symbol
true
. This will need to be evaluated once the end of the command is reached. At this point, don't know if it has any arguments. Store command in execution buffer. - Found symbol
||
. Previous command is now complete, so evaluate it. Command (buffer) being executed:true
. Result of evaluation: 0 (i.e. success). Store result 0 in "last evaluation" register. Now consider symbol||
itself. This depends on the result of the last evaluation being non-zero. Checked "last evaluation" register and found 0. Since 0 is not non-zero, the following command does not need to be evaluated. - Found symbol
echo
. Can ignore this symbol, because the following command did not need to be evaluated. - Found symbol
aaa
. This is an argument to commandecho
(3), but sinceecho
(3) did not need to be evaluated, it can be ignored. - Found symbol
&&
. This depends on the result of the last evaluation being zero. Checked "last evaluation" register and found 0. Since 0 is zero, the following command does need to be evaluated. - Found symbol
echo
. This command needs to be evaluated once the end of the command is reached, because the following command did need to be evaluated. Store command in execution buffer. - Found symbol
bbb
. This is an argument to commandecho
(6). Sinceecho
did need to be evaluated, addbbb
to execution buffer. - Reached end of line. Previous command is now complete and did need to be evaluated. Command (buffer) being executed:
echo bbb
. Result of evaluation: 0 (i.e. success). Store result 0 in "last evaluation" register.
And of course, the last step causes bbb
to be echoed to the console.
add a comment |
I also got confused by this but here's how I think about the way Bash reads your statement (as it reads the symbols left to right):
- Found symbol
true
. This will need to be evaluated once the end of the command is reached. At this point, don't know if it has any arguments. Store command in execution buffer. - Found symbol
||
. Previous command is now complete, so evaluate it. Command (buffer) being executed:true
. Result of evaluation: 0 (i.e. success). Store result 0 in "last evaluation" register. Now consider symbol||
itself. This depends on the result of the last evaluation being non-zero. Checked "last evaluation" register and found 0. Since 0 is not non-zero, the following command does not need to be evaluated. - Found symbol
echo
. Can ignore this symbol, because the following command did not need to be evaluated. - Found symbol
aaa
. This is an argument to commandecho
(3), but sinceecho
(3) did not need to be evaluated, it can be ignored. - Found symbol
&&
. This depends on the result of the last evaluation being zero. Checked "last evaluation" register and found 0. Since 0 is zero, the following command does need to be evaluated. - Found symbol
echo
. This command needs to be evaluated once the end of the command is reached, because the following command did need to be evaluated. Store command in execution buffer. - Found symbol
bbb
. This is an argument to commandecho
(6). Sinceecho
did need to be evaluated, addbbb
to execution buffer. - Reached end of line. Previous command is now complete and did need to be evaluated. Command (buffer) being executed:
echo bbb
. Result of evaluation: 0 (i.e. success). Store result 0 in "last evaluation" register.
And of course, the last step causes bbb
to be echoed to the console.
add a comment |
I also got confused by this but here's how I think about the way Bash reads your statement (as it reads the symbols left to right):
- Found symbol
true
. This will need to be evaluated once the end of the command is reached. At this point, don't know if it has any arguments. Store command in execution buffer. - Found symbol
||
. Previous command is now complete, so evaluate it. Command (buffer) being executed:true
. Result of evaluation: 0 (i.e. success). Store result 0 in "last evaluation" register. Now consider symbol||
itself. This depends on the result of the last evaluation being non-zero. Checked "last evaluation" register and found 0. Since 0 is not non-zero, the following command does not need to be evaluated. - Found symbol
echo
. Can ignore this symbol, because the following command did not need to be evaluated. - Found symbol
aaa
. This is an argument to commandecho
(3), but sinceecho
(3) did not need to be evaluated, it can be ignored. - Found symbol
&&
. This depends on the result of the last evaluation being zero. Checked "last evaluation" register and found 0. Since 0 is zero, the following command does need to be evaluated. - Found symbol
echo
. This command needs to be evaluated once the end of the command is reached, because the following command did need to be evaluated. Store command in execution buffer. - Found symbol
bbb
. This is an argument to commandecho
(6). Sinceecho
did need to be evaluated, addbbb
to execution buffer. - Reached end of line. Previous command is now complete and did need to be evaluated. Command (buffer) being executed:
echo bbb
. Result of evaluation: 0 (i.e. success). Store result 0 in "last evaluation" register.
And of course, the last step causes bbb
to be echoed to the console.
I also got confused by this but here's how I think about the way Bash reads your statement (as it reads the symbols left to right):
- Found symbol
true
. This will need to be evaluated once the end of the command is reached. At this point, don't know if it has any arguments. Store command in execution buffer. - Found symbol
||
. Previous command is now complete, so evaluate it. Command (buffer) being executed:true
. Result of evaluation: 0 (i.e. success). Store result 0 in "last evaluation" register. Now consider symbol||
itself. This depends on the result of the last evaluation being non-zero. Checked "last evaluation" register and found 0. Since 0 is not non-zero, the following command does not need to be evaluated. - Found symbol
echo
. Can ignore this symbol, because the following command did not need to be evaluated. - Found symbol
aaa
. This is an argument to commandecho
(3), but sinceecho
(3) did not need to be evaluated, it can be ignored. - Found symbol
&&
. This depends on the result of the last evaluation being zero. Checked "last evaluation" register and found 0. Since 0 is zero, the following command does need to be evaluated. - Found symbol
echo
. This command needs to be evaluated once the end of the command is reached, because the following command did need to be evaluated. Store command in execution buffer. - Found symbol
bbb
. This is an argument to commandecho
(6). Sinceecho
did need to be evaluated, addbbb
to execution buffer. - Reached end of line. Previous command is now complete and did need to be evaluated. Command (buffer) being executed:
echo bbb
. Result of evaluation: 0 (i.e. success). Store result 0 in "last evaluation" register.
And of course, the last step causes bbb
to be echoed to the console.
answered Jan 25 '18 at 20:00
KidburlaKidburla
5531313
5531313
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f88850%2fprecedence-of-the-shell-logical-operators%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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