Bash block and return codes — need explanation
I've been using Bash for a long time, but it seems I still miss something. Please consider this code:
function surprise {
true && {
echo 'Expected';
false;
} || {
echo 'Unexpected';
}
}
surprise;
which is shortened demonstration of my real problem and the output:
Expected
Unexpected
Till now I have thought, that whatever "Expected" block returns does not affect ||
in front of the "Unexpected" block, but it seems, like ||
is not checked against the output of true
command, but in fact of the false
command inside brackets.
Can someone, please, explain, what actually just happened? Thank you in advance.
bash
add a comment |
I've been using Bash for a long time, but it seems I still miss something. Please consider this code:
function surprise {
true && {
echo 'Expected';
false;
} || {
echo 'Unexpected';
}
}
surprise;
which is shortened demonstration of my real problem and the output:
Expected
Unexpected
Till now I have thought, that whatever "Expected" block returns does not affect ||
in front of the "Unexpected" block, but it seems, like ||
is not checked against the output of true
command, but in fact of the false
command inside brackets.
Can someone, please, explain, what actually just happened? Thank you in advance.
bash
add a comment |
I've been using Bash for a long time, but it seems I still miss something. Please consider this code:
function surprise {
true && {
echo 'Expected';
false;
} || {
echo 'Unexpected';
}
}
surprise;
which is shortened demonstration of my real problem and the output:
Expected
Unexpected
Till now I have thought, that whatever "Expected" block returns does not affect ||
in front of the "Unexpected" block, but it seems, like ||
is not checked against the output of true
command, but in fact of the false
command inside brackets.
Can someone, please, explain, what actually just happened? Thank you in advance.
bash
I've been using Bash for a long time, but it seems I still miss something. Please consider this code:
function surprise {
true && {
echo 'Expected';
false;
} || {
echo 'Unexpected';
}
}
surprise;
which is shortened demonstration of my real problem and the output:
Expected
Unexpected
Till now I have thought, that whatever "Expected" block returns does not affect ||
in front of the "Unexpected" block, but it seems, like ||
is not checked against the output of true
command, but in fact of the false
command inside brackets.
Can someone, please, explain, what actually just happened? Thank you in advance.
bash
bash
asked Jan 29 at 19:44
CromaxCromax
1034
1034
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
it seems, like || is not checked against the output of true command, but in fact of the false command inside brackets.
You could say that's the case.
x && y || z
is not an if/then/else structure, nor should be used as one. It is a combination of boolean operators – the equivalent of "x AND y OR z" – and will evaluate as many commands as it needs to in order to determine the result. (The evaluation is left-to-right unless grouped by parentheses or braces, just like in most programming languages, so the order is (x && y) || z
.)
So in order to determine the result of x && y
, when x is true, y must also be evaluated. On the other hand, when x is false, the result will be false no matter what, so it'll just short-circuit and skip the evaluation of y.
Whether the values in between are single commands or {cmd; cmd; cmd}
blocks actually doesn't matter at all; in this situation it merely helps you see the actual effects.
The short-circuit... I really thought of&&
and||
more likeif-then-else
, but now I get it--thanks!
– Cromax
Jan 29 at 20:12
add a comment |
First: you can think of each of the "blocks" as just complex commands, not something significantly different. Thus, what you really have is just:
cmd1 && cmd2 || cmd3
...and the fact that cmd2
and cmd3
are blocks rather than simple commands doesn't matter. Now, the important thing is that given that command sequence, the logical precedence of &&
and ||
"operators" makes it something like this:
( cmd1 && cmd2 ) || cmd3
(Note: actually, those parentheses would force a subshell. I'm ignoring that.) If you look at the logical structure of that, it's ( something ) || cmd3
, so clearly it's going to run cmd3
if something
fails. But something
is actually cmd1 && cmd2
, which succeeds if *both cmd1
and cmd2
succeed -- which means it fails if either cmd1
or cmd2
fails.
So, logically, that'll wind up running cmd3
if either cmd1
or cmd2
fails. In your actual code, cmd2
always fails, so cmd3
always runs.
add a comment |
The double and (&&
) and the double pipe (||
) have meaning in process control in Linux.
Think of them as logical operators.
command1 && command2
or
command1 || command2
Or
command1 && command2 || command3
Basically, in all 3 cases, command1
runs. If it has a NON-ZERO exit status (an error of some type) it is considered to not have successfully run.
With the &&
- thinking of a logical AND in programming - there is no need to run the second command, because the first one failed in some way.
With the ||
- thinking of a logical OR - the if the first is successful (exit 0) there is no need to check the second condition - only one or the other has to be successful.
With the 3rd example, if command1
is successful, it will run command2
. If it wasn't successful, it will instead run command3
In your example, the ||
is detecting the exit status of your false
command.
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "3"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
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%2fsuperuser.com%2fquestions%2f1399781%2fbash-block-and-return-codes-need-explanation%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
it seems, like || is not checked against the output of true command, but in fact of the false command inside brackets.
You could say that's the case.
x && y || z
is not an if/then/else structure, nor should be used as one. It is a combination of boolean operators – the equivalent of "x AND y OR z" – and will evaluate as many commands as it needs to in order to determine the result. (The evaluation is left-to-right unless grouped by parentheses or braces, just like in most programming languages, so the order is (x && y) || z
.)
So in order to determine the result of x && y
, when x is true, y must also be evaluated. On the other hand, when x is false, the result will be false no matter what, so it'll just short-circuit and skip the evaluation of y.
Whether the values in between are single commands or {cmd; cmd; cmd}
blocks actually doesn't matter at all; in this situation it merely helps you see the actual effects.
The short-circuit... I really thought of&&
and||
more likeif-then-else
, but now I get it--thanks!
– Cromax
Jan 29 at 20:12
add a comment |
it seems, like || is not checked against the output of true command, but in fact of the false command inside brackets.
You could say that's the case.
x && y || z
is not an if/then/else structure, nor should be used as one. It is a combination of boolean operators – the equivalent of "x AND y OR z" – and will evaluate as many commands as it needs to in order to determine the result. (The evaluation is left-to-right unless grouped by parentheses or braces, just like in most programming languages, so the order is (x && y) || z
.)
So in order to determine the result of x && y
, when x is true, y must also be evaluated. On the other hand, when x is false, the result will be false no matter what, so it'll just short-circuit and skip the evaluation of y.
Whether the values in between are single commands or {cmd; cmd; cmd}
blocks actually doesn't matter at all; in this situation it merely helps you see the actual effects.
The short-circuit... I really thought of&&
and||
more likeif-then-else
, but now I get it--thanks!
– Cromax
Jan 29 at 20:12
add a comment |
it seems, like || is not checked against the output of true command, but in fact of the false command inside brackets.
You could say that's the case.
x && y || z
is not an if/then/else structure, nor should be used as one. It is a combination of boolean operators – the equivalent of "x AND y OR z" – and will evaluate as many commands as it needs to in order to determine the result. (The evaluation is left-to-right unless grouped by parentheses or braces, just like in most programming languages, so the order is (x && y) || z
.)
So in order to determine the result of x && y
, when x is true, y must also be evaluated. On the other hand, when x is false, the result will be false no matter what, so it'll just short-circuit and skip the evaluation of y.
Whether the values in between are single commands or {cmd; cmd; cmd}
blocks actually doesn't matter at all; in this situation it merely helps you see the actual effects.
it seems, like || is not checked against the output of true command, but in fact of the false command inside brackets.
You could say that's the case.
x && y || z
is not an if/then/else structure, nor should be used as one. It is a combination of boolean operators – the equivalent of "x AND y OR z" – and will evaluate as many commands as it needs to in order to determine the result. (The evaluation is left-to-right unless grouped by parentheses or braces, just like in most programming languages, so the order is (x && y) || z
.)
So in order to determine the result of x && y
, when x is true, y must also be evaluated. On the other hand, when x is false, the result will be false no matter what, so it'll just short-circuit and skip the evaluation of y.
Whether the values in between are single commands or {cmd; cmd; cmd}
blocks actually doesn't matter at all; in this situation it merely helps you see the actual effects.
edited Jan 29 at 20:20
community wiki
2 revs
grawity
The short-circuit... I really thought of&&
and||
more likeif-then-else
, but now I get it--thanks!
– Cromax
Jan 29 at 20:12
add a comment |
The short-circuit... I really thought of&&
and||
more likeif-then-else
, but now I get it--thanks!
– Cromax
Jan 29 at 20:12
The short-circuit... I really thought of
&&
and ||
more like if-then-else
, but now I get it--thanks!– Cromax
Jan 29 at 20:12
The short-circuit... I really thought of
&&
and ||
more like if-then-else
, but now I get it--thanks!– Cromax
Jan 29 at 20:12
add a comment |
First: you can think of each of the "blocks" as just complex commands, not something significantly different. Thus, what you really have is just:
cmd1 && cmd2 || cmd3
...and the fact that cmd2
and cmd3
are blocks rather than simple commands doesn't matter. Now, the important thing is that given that command sequence, the logical precedence of &&
and ||
"operators" makes it something like this:
( cmd1 && cmd2 ) || cmd3
(Note: actually, those parentheses would force a subshell. I'm ignoring that.) If you look at the logical structure of that, it's ( something ) || cmd3
, so clearly it's going to run cmd3
if something
fails. But something
is actually cmd1 && cmd2
, which succeeds if *both cmd1
and cmd2
succeed -- which means it fails if either cmd1
or cmd2
fails.
So, logically, that'll wind up running cmd3
if either cmd1
or cmd2
fails. In your actual code, cmd2
always fails, so cmd3
always runs.
add a comment |
First: you can think of each of the "blocks" as just complex commands, not something significantly different. Thus, what you really have is just:
cmd1 && cmd2 || cmd3
...and the fact that cmd2
and cmd3
are blocks rather than simple commands doesn't matter. Now, the important thing is that given that command sequence, the logical precedence of &&
and ||
"operators" makes it something like this:
( cmd1 && cmd2 ) || cmd3
(Note: actually, those parentheses would force a subshell. I'm ignoring that.) If you look at the logical structure of that, it's ( something ) || cmd3
, so clearly it's going to run cmd3
if something
fails. But something
is actually cmd1 && cmd2
, which succeeds if *both cmd1
and cmd2
succeed -- which means it fails if either cmd1
or cmd2
fails.
So, logically, that'll wind up running cmd3
if either cmd1
or cmd2
fails. In your actual code, cmd2
always fails, so cmd3
always runs.
add a comment |
First: you can think of each of the "blocks" as just complex commands, not something significantly different. Thus, what you really have is just:
cmd1 && cmd2 || cmd3
...and the fact that cmd2
and cmd3
are blocks rather than simple commands doesn't matter. Now, the important thing is that given that command sequence, the logical precedence of &&
and ||
"operators" makes it something like this:
( cmd1 && cmd2 ) || cmd3
(Note: actually, those parentheses would force a subshell. I'm ignoring that.) If you look at the logical structure of that, it's ( something ) || cmd3
, so clearly it's going to run cmd3
if something
fails. But something
is actually cmd1 && cmd2
, which succeeds if *both cmd1
and cmd2
succeed -- which means it fails if either cmd1
or cmd2
fails.
So, logically, that'll wind up running cmd3
if either cmd1
or cmd2
fails. In your actual code, cmd2
always fails, so cmd3
always runs.
First: you can think of each of the "blocks" as just complex commands, not something significantly different. Thus, what you really have is just:
cmd1 && cmd2 || cmd3
...and the fact that cmd2
and cmd3
are blocks rather than simple commands doesn't matter. Now, the important thing is that given that command sequence, the logical precedence of &&
and ||
"operators" makes it something like this:
( cmd1 && cmd2 ) || cmd3
(Note: actually, those parentheses would force a subshell. I'm ignoring that.) If you look at the logical structure of that, it's ( something ) || cmd3
, so clearly it's going to run cmd3
if something
fails. But something
is actually cmd1 && cmd2
, which succeeds if *both cmd1
and cmd2
succeed -- which means it fails if either cmd1
or cmd2
fails.
So, logically, that'll wind up running cmd3
if either cmd1
or cmd2
fails. In your actual code, cmd2
always fails, so cmd3
always runs.
answered Jan 29 at 20:06
Gordon DavissonGordon Davisson
26k44350
26k44350
add a comment |
add a comment |
The double and (&&
) and the double pipe (||
) have meaning in process control in Linux.
Think of them as logical operators.
command1 && command2
or
command1 || command2
Or
command1 && command2 || command3
Basically, in all 3 cases, command1
runs. If it has a NON-ZERO exit status (an error of some type) it is considered to not have successfully run.
With the &&
- thinking of a logical AND in programming - there is no need to run the second command, because the first one failed in some way.
With the ||
- thinking of a logical OR - the if the first is successful (exit 0) there is no need to check the second condition - only one or the other has to be successful.
With the 3rd example, if command1
is successful, it will run command2
. If it wasn't successful, it will instead run command3
In your example, the ||
is detecting the exit status of your false
command.
add a comment |
The double and (&&
) and the double pipe (||
) have meaning in process control in Linux.
Think of them as logical operators.
command1 && command2
or
command1 || command2
Or
command1 && command2 || command3
Basically, in all 3 cases, command1
runs. If it has a NON-ZERO exit status (an error of some type) it is considered to not have successfully run.
With the &&
- thinking of a logical AND in programming - there is no need to run the second command, because the first one failed in some way.
With the ||
- thinking of a logical OR - the if the first is successful (exit 0) there is no need to check the second condition - only one or the other has to be successful.
With the 3rd example, if command1
is successful, it will run command2
. If it wasn't successful, it will instead run command3
In your example, the ||
is detecting the exit status of your false
command.
add a comment |
The double and (&&
) and the double pipe (||
) have meaning in process control in Linux.
Think of them as logical operators.
command1 && command2
or
command1 || command2
Or
command1 && command2 || command3
Basically, in all 3 cases, command1
runs. If it has a NON-ZERO exit status (an error of some type) it is considered to not have successfully run.
With the &&
- thinking of a logical AND in programming - there is no need to run the second command, because the first one failed in some way.
With the ||
- thinking of a logical OR - the if the first is successful (exit 0) there is no need to check the second condition - only one or the other has to be successful.
With the 3rd example, if command1
is successful, it will run command2
. If it wasn't successful, it will instead run command3
In your example, the ||
is detecting the exit status of your false
command.
The double and (&&
) and the double pipe (||
) have meaning in process control in Linux.
Think of them as logical operators.
command1 && command2
or
command1 || command2
Or
command1 && command2 || command3
Basically, in all 3 cases, command1
runs. If it has a NON-ZERO exit status (an error of some type) it is considered to not have successfully run.
With the &&
- thinking of a logical AND in programming - there is no need to run the second command, because the first one failed in some way.
With the ||
- thinking of a logical OR - the if the first is successful (exit 0) there is no need to check the second condition - only one or the other has to be successful.
With the 3rd example, if command1
is successful, it will run command2
. If it wasn't successful, it will instead run command3
In your example, the ||
is detecting the exit status of your false
command.
answered Jan 29 at 20:02
ivanivanivanivan
1,25427
1,25427
add a comment |
add a comment |
Thanks for contributing an answer to Super User!
- 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%2fsuperuser.com%2fquestions%2f1399781%2fbash-block-and-return-codes-need-explanation%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