âfoo && bar || bazâ in bash behaving differently from âif foo; then bar; else bazâ [duplicate]
Clash Royale CLAN TAG#URR8PPP
up vote
5
down vote
favorite
This question already has an answer here:
Precedence of the shell logical operators &&, ||
4 answers
I thought
[ 1 -eq $1 ] && echo "yes" || echo "no"
Acts like
if [ 1 -eq $1 ]; then
echo "yes"
else
echo "no"
fi
But, when I run this script (nocmd
is a non-existing command)
#!/bin/bash
[ 1 -eq $1 ] && nocmd "yes" || echo "no"
I get a strange output for parameter '1':
me@ubuntu:/tmp$ ./ddd.sh 0
no
me@ubuntu:/tmp$ ./ddd.sh 1
./sh.sh: line 3: nocmd: command not found
no
Looks like it acts like:
if [ 1 -eq $1 ]; then
nocmd "yes"
if [ $? -ne 0 ]; then
echo "no"
fi
else
echo "no"
fi
Is it fine? Am I missing something?
bash shell-script
marked as duplicate by G-Man, muru, Jakuje, ñÃÂsýù÷, Hunter.S.Thompson Jan 31 at 10:59
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
add a comment |Â
up vote
5
down vote
favorite
This question already has an answer here:
Precedence of the shell logical operators &&, ||
4 answers
I thought
[ 1 -eq $1 ] && echo "yes" || echo "no"
Acts like
if [ 1 -eq $1 ]; then
echo "yes"
else
echo "no"
fi
But, when I run this script (nocmd
is a non-existing command)
#!/bin/bash
[ 1 -eq $1 ] && nocmd "yes" || echo "no"
I get a strange output for parameter '1':
me@ubuntu:/tmp$ ./ddd.sh 0
no
me@ubuntu:/tmp$ ./ddd.sh 1
./sh.sh: line 3: nocmd: command not found
no
Looks like it acts like:
if [ 1 -eq $1 ]; then
nocmd "yes"
if [ $? -ne 0 ]; then
echo "no"
fi
else
echo "no"
fi
Is it fine? Am I missing something?
bash shell-script
marked as duplicate by G-Man, muru, Jakuje, ñÃÂsýù÷, Hunter.S.Thompson Jan 31 at 10:59
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
4
It's no strange thing there, when you ran with./ddd.sh 0
this part will check[ 1 -eq $1 ]
it's not true (false) (1!=0), so this part won't run&& nocmd "yes"
and this part will run|| echo "no"
, but when it's true1=1
it will execute&& nocmd "yes"
part and since shell doesn't recognizenocmd
command, it's reported error.... command not found
and again second part will run|| echo "no"
.
â Ã±ÃÂsýù÷
Jan 30 at 17:00
add a comment |Â
up vote
5
down vote
favorite
up vote
5
down vote
favorite
This question already has an answer here:
Precedence of the shell logical operators &&, ||
4 answers
I thought
[ 1 -eq $1 ] && echo "yes" || echo "no"
Acts like
if [ 1 -eq $1 ]; then
echo "yes"
else
echo "no"
fi
But, when I run this script (nocmd
is a non-existing command)
#!/bin/bash
[ 1 -eq $1 ] && nocmd "yes" || echo "no"
I get a strange output for parameter '1':
me@ubuntu:/tmp$ ./ddd.sh 0
no
me@ubuntu:/tmp$ ./ddd.sh 1
./sh.sh: line 3: nocmd: command not found
no
Looks like it acts like:
if [ 1 -eq $1 ]; then
nocmd "yes"
if [ $? -ne 0 ]; then
echo "no"
fi
else
echo "no"
fi
Is it fine? Am I missing something?
bash shell-script
This question already has an answer here:
Precedence of the shell logical operators &&, ||
4 answers
I thought
[ 1 -eq $1 ] && echo "yes" || echo "no"
Acts like
if [ 1 -eq $1 ]; then
echo "yes"
else
echo "no"
fi
But, when I run this script (nocmd
is a non-existing command)
#!/bin/bash
[ 1 -eq $1 ] && nocmd "yes" || echo "no"
I get a strange output for parameter '1':
me@ubuntu:/tmp$ ./ddd.sh 0
no
me@ubuntu:/tmp$ ./ddd.sh 1
./sh.sh: line 3: nocmd: command not found
no
Looks like it acts like:
if [ 1 -eq $1 ]; then
nocmd "yes"
if [ $? -ne 0 ]; then
echo "no"
fi
else
echo "no"
fi
Is it fine? Am I missing something?
This question already has an answer here:
Precedence of the shell logical operators &&, ||
4 answers
bash shell-script
edited Jan 30 at 21:52
Charles Duffy
736413
736413
asked Jan 30 at 16:55
hudac
327312
327312
marked as duplicate by G-Man, muru, Jakuje, ñÃÂsýù÷, Hunter.S.Thompson Jan 31 at 10:59
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
marked as duplicate by G-Man, muru, Jakuje, ñÃÂsýù÷, Hunter.S.Thompson Jan 31 at 10:59
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
4
It's no strange thing there, when you ran with./ddd.sh 0
this part will check[ 1 -eq $1 ]
it's not true (false) (1!=0), so this part won't run&& nocmd "yes"
and this part will run|| echo "no"
, but when it's true1=1
it will execute&& nocmd "yes"
part and since shell doesn't recognizenocmd
command, it's reported error.... command not found
and again second part will run|| echo "no"
.
â Ã±ÃÂsýù÷
Jan 30 at 17:00
add a comment |Â
4
It's no strange thing there, when you ran with./ddd.sh 0
this part will check[ 1 -eq $1 ]
it's not true (false) (1!=0), so this part won't run&& nocmd "yes"
and this part will run|| echo "no"
, but when it's true1=1
it will execute&& nocmd "yes"
part and since shell doesn't recognizenocmd
command, it's reported error.... command not found
and again second part will run|| echo "no"
.
â Ã±ÃÂsýù÷
Jan 30 at 17:00
4
4
It's no strange thing there, when you ran with
./ddd.sh 0
this part will check [ 1 -eq $1 ]
it's not true (false) (1!=0), so this part won't run && nocmd "yes"
and this part will run || echo "no"
, but when it's true 1=1
it will execute && nocmd "yes"
part and since shell doesn't recognize nocmd
command, it's reported error .... command not found
and again second part will run || echo "no"
.â Ã±ÃÂsýù÷
Jan 30 at 17:00
It's no strange thing there, when you ran with
./ddd.sh 0
this part will check [ 1 -eq $1 ]
it's not true (false) (1!=0), so this part won't run && nocmd "yes"
and this part will run || echo "no"
, but when it's true 1=1
it will execute && nocmd "yes"
part and since shell doesn't recognize nocmd
command, it's reported error .... command not found
and again second part will run || echo "no"
.â Ã±ÃÂsýù÷
Jan 30 at 17:00
add a comment |Â
3 Answers
3
active
oldest
votes
up vote
19
down vote
accepted
Except for the overall exit status, it acts like:
if
!
[ 1 -eq $1 ] && nocmd "yes"
then
echo no
fi
In:
A || B
B
is executed iff A
fails. That's a OR operator.
In your case A
is [ 1 -eq $1 ] && nocmd "yes"
where nocmd
is run iff [
succeeds (a AND operator), in which case the exit status of A
will be that of nocmd
. In other words echo no
will be executed if either [
or nocmd "yes"
fails (bearing in mind that nocmd
is only run if [
succeeds).
Those x && y || z
are dirty hacks. They are best avoided for that very reason. Use a if
/then
/else
construct if you do want a if/then/else logic. Use x && y || z
only if you want z
to be unless both x
and y
succeeded.
Even in:
cmd && echo OK || echo >&2 KO
The echo OK
could fail under some pathological conditions (like stdout going to a file on a full filesystem), and echo >&2 KO
could end up being executed as well.
$ bash -c 'true && echo OK || echo KO >&2' > /dev/full
bash: line 0: echo: write error: No space left on device
KO
add a comment |Â
up vote
5
down vote
Well, what actually happens is this (and this is how &&
and ||
works)
test 1 -eq $1
ret=$?
if [ $ret -eq 0 ]; then
nocmd "yes"
ret=$?
fi
if [ $ret -ne 0 ]; then
echo "no"
fi
In your case, if $1
does not equal 1
, or is not a valid number, then you have a non-zero $?
, and the first if
is skipped, and the second if
prints "no". If $1
equals 1
, then nocmd "yes"
is executed, returning a non-zero $?
, and "no" is also echoed.
That's not exactly true, and the reason is a bit weird. An if statement returns0
if it doesn't run either of thethen
andelse
branches. So if the first test fails,$?
is zero on the second test, always.if false ; then echo x; fi; echo $?
prints0
.
â ilkkachu
Jan 30 at 17:40
@ilkkachu Noted. I didn't know that before.
â Weijun Zhou
Jan 30 at 17:41
It's really more like that, at least I get the same result for that construct and the&& .. ||
chain
â ilkkachu
Jan 30 at 17:43
@ilkkachu So you mean that my original version of code is valid but for more complicated reasons?
â Weijun Zhou
Jan 30 at 17:45
1
no, with the test directly against$?
, the double-if gives a different result from the&& ||
, since the first if-statement throws the second off. With the temporary variable the behavior matches. See: pastebin.com/q0Ct0Zw8 for the difference without the temp
â ilkkachu
Jan 30 at 17:56
add a comment |Â
up vote
3
down vote
What you're missing is that &&
and ||
operate on exit status of commands to the left of them - left associativity. You have here some group of commands || echo "no"
, and no
will be echoed if and only if that group of commands returns non-success exit status.
What is that group of commands ? In first case you have [ 1 -eq "$1" ] && echo "yes"
. If [
portion failed, that'd be counted as fail exit status for [ 1 -eq "$1" ] && echo "yes"
, therefore you'd echo "no"
would run. Also because of left associativity, when "$1" is 1, the [ 1 -eq $1 ]
returns success, then lets nocmd
run which doesn't exist and shell will return error exit status, the whole group will have exit status of fail, hence `"no" is echoed.
By contrast, in your if statement
if [ 1 -eq $1 ]; then
echo "yes"
else
echo "no"
fi
which route to take depends only on exit status of [
portion. In [ 1 -eq "$1" ] && echo "Yes" || echo "no"
echo also plays role as to whether or not echo "no"
runs.
Your second if statement example is also different
if [ 1 -eq $1 ]; then
nocmd "yes"
if [ $? -ne 0 ]; then
echo "no"
fi
else
echo "no"
fi
The echo "no"
after else
doesn't depend on what happens to nocmd
as in the chaining of logical operators. Sure you still do the echo "no"
part after doing nocmd
, but here its exit status isn't grouped together with the whole if
portion to which it belongs.
add a comment |Â
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
19
down vote
accepted
Except for the overall exit status, it acts like:
if
!
[ 1 -eq $1 ] && nocmd "yes"
then
echo no
fi
In:
A || B
B
is executed iff A
fails. That's a OR operator.
In your case A
is [ 1 -eq $1 ] && nocmd "yes"
where nocmd
is run iff [
succeeds (a AND operator), in which case the exit status of A
will be that of nocmd
. In other words echo no
will be executed if either [
or nocmd "yes"
fails (bearing in mind that nocmd
is only run if [
succeeds).
Those x && y || z
are dirty hacks. They are best avoided for that very reason. Use a if
/then
/else
construct if you do want a if/then/else logic. Use x && y || z
only if you want z
to be unless both x
and y
succeeded.
Even in:
cmd && echo OK || echo >&2 KO
The echo OK
could fail under some pathological conditions (like stdout going to a file on a full filesystem), and echo >&2 KO
could end up being executed as well.
$ bash -c 'true && echo OK || echo KO >&2' > /dev/full
bash: line 0: echo: write error: No space left on device
KO
add a comment |Â
up vote
19
down vote
accepted
Except for the overall exit status, it acts like:
if
!
[ 1 -eq $1 ] && nocmd "yes"
then
echo no
fi
In:
A || B
B
is executed iff A
fails. That's a OR operator.
In your case A
is [ 1 -eq $1 ] && nocmd "yes"
where nocmd
is run iff [
succeeds (a AND operator), in which case the exit status of A
will be that of nocmd
. In other words echo no
will be executed if either [
or nocmd "yes"
fails (bearing in mind that nocmd
is only run if [
succeeds).
Those x && y || z
are dirty hacks. They are best avoided for that very reason. Use a if
/then
/else
construct if you do want a if/then/else logic. Use x && y || z
only if you want z
to be unless both x
and y
succeeded.
Even in:
cmd && echo OK || echo >&2 KO
The echo OK
could fail under some pathological conditions (like stdout going to a file on a full filesystem), and echo >&2 KO
could end up being executed as well.
$ bash -c 'true && echo OK || echo KO >&2' > /dev/full
bash: line 0: echo: write error: No space left on device
KO
add a comment |Â
up vote
19
down vote
accepted
up vote
19
down vote
accepted
Except for the overall exit status, it acts like:
if
!
[ 1 -eq $1 ] && nocmd "yes"
then
echo no
fi
In:
A || B
B
is executed iff A
fails. That's a OR operator.
In your case A
is [ 1 -eq $1 ] && nocmd "yes"
where nocmd
is run iff [
succeeds (a AND operator), in which case the exit status of A
will be that of nocmd
. In other words echo no
will be executed if either [
or nocmd "yes"
fails (bearing in mind that nocmd
is only run if [
succeeds).
Those x && y || z
are dirty hacks. They are best avoided for that very reason. Use a if
/then
/else
construct if you do want a if/then/else logic. Use x && y || z
only if you want z
to be unless both x
and y
succeeded.
Even in:
cmd && echo OK || echo >&2 KO
The echo OK
could fail under some pathological conditions (like stdout going to a file on a full filesystem), and echo >&2 KO
could end up being executed as well.
$ bash -c 'true && echo OK || echo KO >&2' > /dev/full
bash: line 0: echo: write error: No space left on device
KO
Except for the overall exit status, it acts like:
if
!
[ 1 -eq $1 ] && nocmd "yes"
then
echo no
fi
In:
A || B
B
is executed iff A
fails. That's a OR operator.
In your case A
is [ 1 -eq $1 ] && nocmd "yes"
where nocmd
is run iff [
succeeds (a AND operator), in which case the exit status of A
will be that of nocmd
. In other words echo no
will be executed if either [
or nocmd "yes"
fails (bearing in mind that nocmd
is only run if [
succeeds).
Those x && y || z
are dirty hacks. They are best avoided for that very reason. Use a if
/then
/else
construct if you do want a if/then/else logic. Use x && y || z
only if you want z
to be unless both x
and y
succeeded.
Even in:
cmd && echo OK || echo >&2 KO
The echo OK
could fail under some pathological conditions (like stdout going to a file on a full filesystem), and echo >&2 KO
could end up being executed as well.
$ bash -c 'true && echo OK || echo KO >&2' > /dev/full
bash: line 0: echo: write error: No space left on device
KO
edited Jan 30 at 17:22
answered Jan 30 at 17:01
Stéphane Chazelas
281k53516847
281k53516847
add a comment |Â
add a comment |Â
up vote
5
down vote
Well, what actually happens is this (and this is how &&
and ||
works)
test 1 -eq $1
ret=$?
if [ $ret -eq 0 ]; then
nocmd "yes"
ret=$?
fi
if [ $ret -ne 0 ]; then
echo "no"
fi
In your case, if $1
does not equal 1
, or is not a valid number, then you have a non-zero $?
, and the first if
is skipped, and the second if
prints "no". If $1
equals 1
, then nocmd "yes"
is executed, returning a non-zero $?
, and "no" is also echoed.
That's not exactly true, and the reason is a bit weird. An if statement returns0
if it doesn't run either of thethen
andelse
branches. So if the first test fails,$?
is zero on the second test, always.if false ; then echo x; fi; echo $?
prints0
.
â ilkkachu
Jan 30 at 17:40
@ilkkachu Noted. I didn't know that before.
â Weijun Zhou
Jan 30 at 17:41
It's really more like that, at least I get the same result for that construct and the&& .. ||
chain
â ilkkachu
Jan 30 at 17:43
@ilkkachu So you mean that my original version of code is valid but for more complicated reasons?
â Weijun Zhou
Jan 30 at 17:45
1
no, with the test directly against$?
, the double-if gives a different result from the&& ||
, since the first if-statement throws the second off. With the temporary variable the behavior matches. See: pastebin.com/q0Ct0Zw8 for the difference without the temp
â ilkkachu
Jan 30 at 17:56
add a comment |Â
up vote
5
down vote
Well, what actually happens is this (and this is how &&
and ||
works)
test 1 -eq $1
ret=$?
if [ $ret -eq 0 ]; then
nocmd "yes"
ret=$?
fi
if [ $ret -ne 0 ]; then
echo "no"
fi
In your case, if $1
does not equal 1
, or is not a valid number, then you have a non-zero $?
, and the first if
is skipped, and the second if
prints "no". If $1
equals 1
, then nocmd "yes"
is executed, returning a non-zero $?
, and "no" is also echoed.
That's not exactly true, and the reason is a bit weird. An if statement returns0
if it doesn't run either of thethen
andelse
branches. So if the first test fails,$?
is zero on the second test, always.if false ; then echo x; fi; echo $?
prints0
.
â ilkkachu
Jan 30 at 17:40
@ilkkachu Noted. I didn't know that before.
â Weijun Zhou
Jan 30 at 17:41
It's really more like that, at least I get the same result for that construct and the&& .. ||
chain
â ilkkachu
Jan 30 at 17:43
@ilkkachu So you mean that my original version of code is valid but for more complicated reasons?
â Weijun Zhou
Jan 30 at 17:45
1
no, with the test directly against$?
, the double-if gives a different result from the&& ||
, since the first if-statement throws the second off. With the temporary variable the behavior matches. See: pastebin.com/q0Ct0Zw8 for the difference without the temp
â ilkkachu
Jan 30 at 17:56
add a comment |Â
up vote
5
down vote
up vote
5
down vote
Well, what actually happens is this (and this is how &&
and ||
works)
test 1 -eq $1
ret=$?
if [ $ret -eq 0 ]; then
nocmd "yes"
ret=$?
fi
if [ $ret -ne 0 ]; then
echo "no"
fi
In your case, if $1
does not equal 1
, or is not a valid number, then you have a non-zero $?
, and the first if
is skipped, and the second if
prints "no". If $1
equals 1
, then nocmd "yes"
is executed, returning a non-zero $?
, and "no" is also echoed.
Well, what actually happens is this (and this is how &&
and ||
works)
test 1 -eq $1
ret=$?
if [ $ret -eq 0 ]; then
nocmd "yes"
ret=$?
fi
if [ $ret -ne 0 ]; then
echo "no"
fi
In your case, if $1
does not equal 1
, or is not a valid number, then you have a non-zero $?
, and the first if
is skipped, and the second if
prints "no". If $1
equals 1
, then nocmd "yes"
is executed, returning a non-zero $?
, and "no" is also echoed.
edited Jan 30 at 17:42
ilkkachu
49.8k674137
49.8k674137
answered Jan 30 at 17:01
Weijun Zhou
1,434119
1,434119
That's not exactly true, and the reason is a bit weird. An if statement returns0
if it doesn't run either of thethen
andelse
branches. So if the first test fails,$?
is zero on the second test, always.if false ; then echo x; fi; echo $?
prints0
.
â ilkkachu
Jan 30 at 17:40
@ilkkachu Noted. I didn't know that before.
â Weijun Zhou
Jan 30 at 17:41
It's really more like that, at least I get the same result for that construct and the&& .. ||
chain
â ilkkachu
Jan 30 at 17:43
@ilkkachu So you mean that my original version of code is valid but for more complicated reasons?
â Weijun Zhou
Jan 30 at 17:45
1
no, with the test directly against$?
, the double-if gives a different result from the&& ||
, since the first if-statement throws the second off. With the temporary variable the behavior matches. See: pastebin.com/q0Ct0Zw8 for the difference without the temp
â ilkkachu
Jan 30 at 17:56
add a comment |Â
That's not exactly true, and the reason is a bit weird. An if statement returns0
if it doesn't run either of thethen
andelse
branches. So if the first test fails,$?
is zero on the second test, always.if false ; then echo x; fi; echo $?
prints0
.
â ilkkachu
Jan 30 at 17:40
@ilkkachu Noted. I didn't know that before.
â Weijun Zhou
Jan 30 at 17:41
It's really more like that, at least I get the same result for that construct and the&& .. ||
chain
â ilkkachu
Jan 30 at 17:43
@ilkkachu So you mean that my original version of code is valid but for more complicated reasons?
â Weijun Zhou
Jan 30 at 17:45
1
no, with the test directly against$?
, the double-if gives a different result from the&& ||
, since the first if-statement throws the second off. With the temporary variable the behavior matches. See: pastebin.com/q0Ct0Zw8 for the difference without the temp
â ilkkachu
Jan 30 at 17:56
That's not exactly true, and the reason is a bit weird. An if statement returns
0
if it doesn't run either of the then
and else
branches. So if the first test fails, $?
is zero on the second test, always. if false ; then echo x; fi; echo $?
prints 0
.â ilkkachu
Jan 30 at 17:40
That's not exactly true, and the reason is a bit weird. An if statement returns
0
if it doesn't run either of the then
and else
branches. So if the first test fails, $?
is zero on the second test, always. if false ; then echo x; fi; echo $?
prints 0
.â ilkkachu
Jan 30 at 17:40
@ilkkachu Noted. I didn't know that before.
â Weijun Zhou
Jan 30 at 17:41
@ilkkachu Noted. I didn't know that before.
â Weijun Zhou
Jan 30 at 17:41
It's really more like that, at least I get the same result for that construct and the
&& .. ||
chainâ ilkkachu
Jan 30 at 17:43
It's really more like that, at least I get the same result for that construct and the
&& .. ||
chainâ ilkkachu
Jan 30 at 17:43
@ilkkachu So you mean that my original version of code is valid but for more complicated reasons?
â Weijun Zhou
Jan 30 at 17:45
@ilkkachu So you mean that my original version of code is valid but for more complicated reasons?
â Weijun Zhou
Jan 30 at 17:45
1
1
no, with the test directly against
$?
, the double-if gives a different result from the && ||
, since the first if-statement throws the second off. With the temporary variable the behavior matches. See: pastebin.com/q0Ct0Zw8 for the difference without the tempâ ilkkachu
Jan 30 at 17:56
no, with the test directly against
$?
, the double-if gives a different result from the && ||
, since the first if-statement throws the second off. With the temporary variable the behavior matches. See: pastebin.com/q0Ct0Zw8 for the difference without the tempâ ilkkachu
Jan 30 at 17:56
add a comment |Â
up vote
3
down vote
What you're missing is that &&
and ||
operate on exit status of commands to the left of them - left associativity. You have here some group of commands || echo "no"
, and no
will be echoed if and only if that group of commands returns non-success exit status.
What is that group of commands ? In first case you have [ 1 -eq "$1" ] && echo "yes"
. If [
portion failed, that'd be counted as fail exit status for [ 1 -eq "$1" ] && echo "yes"
, therefore you'd echo "no"
would run. Also because of left associativity, when "$1" is 1, the [ 1 -eq $1 ]
returns success, then lets nocmd
run which doesn't exist and shell will return error exit status, the whole group will have exit status of fail, hence `"no" is echoed.
By contrast, in your if statement
if [ 1 -eq $1 ]; then
echo "yes"
else
echo "no"
fi
which route to take depends only on exit status of [
portion. In [ 1 -eq "$1" ] && echo "Yes" || echo "no"
echo also plays role as to whether or not echo "no"
runs.
Your second if statement example is also different
if [ 1 -eq $1 ]; then
nocmd "yes"
if [ $? -ne 0 ]; then
echo "no"
fi
else
echo "no"
fi
The echo "no"
after else
doesn't depend on what happens to nocmd
as in the chaining of logical operators. Sure you still do the echo "no"
part after doing nocmd
, but here its exit status isn't grouped together with the whole if
portion to which it belongs.
add a comment |Â
up vote
3
down vote
What you're missing is that &&
and ||
operate on exit status of commands to the left of them - left associativity. You have here some group of commands || echo "no"
, and no
will be echoed if and only if that group of commands returns non-success exit status.
What is that group of commands ? In first case you have [ 1 -eq "$1" ] && echo "yes"
. If [
portion failed, that'd be counted as fail exit status for [ 1 -eq "$1" ] && echo "yes"
, therefore you'd echo "no"
would run. Also because of left associativity, when "$1" is 1, the [ 1 -eq $1 ]
returns success, then lets nocmd
run which doesn't exist and shell will return error exit status, the whole group will have exit status of fail, hence `"no" is echoed.
By contrast, in your if statement
if [ 1 -eq $1 ]; then
echo "yes"
else
echo "no"
fi
which route to take depends only on exit status of [
portion. In [ 1 -eq "$1" ] && echo "Yes" || echo "no"
echo also plays role as to whether or not echo "no"
runs.
Your second if statement example is also different
if [ 1 -eq $1 ]; then
nocmd "yes"
if [ $? -ne 0 ]; then
echo "no"
fi
else
echo "no"
fi
The echo "no"
after else
doesn't depend on what happens to nocmd
as in the chaining of logical operators. Sure you still do the echo "no"
part after doing nocmd
, but here its exit status isn't grouped together with the whole if
portion to which it belongs.
add a comment |Â
up vote
3
down vote
up vote
3
down vote
What you're missing is that &&
and ||
operate on exit status of commands to the left of them - left associativity. You have here some group of commands || echo "no"
, and no
will be echoed if and only if that group of commands returns non-success exit status.
What is that group of commands ? In first case you have [ 1 -eq "$1" ] && echo "yes"
. If [
portion failed, that'd be counted as fail exit status for [ 1 -eq "$1" ] && echo "yes"
, therefore you'd echo "no"
would run. Also because of left associativity, when "$1" is 1, the [ 1 -eq $1 ]
returns success, then lets nocmd
run which doesn't exist and shell will return error exit status, the whole group will have exit status of fail, hence `"no" is echoed.
By contrast, in your if statement
if [ 1 -eq $1 ]; then
echo "yes"
else
echo "no"
fi
which route to take depends only on exit status of [
portion. In [ 1 -eq "$1" ] && echo "Yes" || echo "no"
echo also plays role as to whether or not echo "no"
runs.
Your second if statement example is also different
if [ 1 -eq $1 ]; then
nocmd "yes"
if [ $? -ne 0 ]; then
echo "no"
fi
else
echo "no"
fi
The echo "no"
after else
doesn't depend on what happens to nocmd
as in the chaining of logical operators. Sure you still do the echo "no"
part after doing nocmd
, but here its exit status isn't grouped together with the whole if
portion to which it belongs.
What you're missing is that &&
and ||
operate on exit status of commands to the left of them - left associativity. You have here some group of commands || echo "no"
, and no
will be echoed if and only if that group of commands returns non-success exit status.
What is that group of commands ? In first case you have [ 1 -eq "$1" ] && echo "yes"
. If [
portion failed, that'd be counted as fail exit status for [ 1 -eq "$1" ] && echo "yes"
, therefore you'd echo "no"
would run. Also because of left associativity, when "$1" is 1, the [ 1 -eq $1 ]
returns success, then lets nocmd
run which doesn't exist and shell will return error exit status, the whole group will have exit status of fail, hence `"no" is echoed.
By contrast, in your if statement
if [ 1 -eq $1 ]; then
echo "yes"
else
echo "no"
fi
which route to take depends only on exit status of [
portion. In [ 1 -eq "$1" ] && echo "Yes" || echo "no"
echo also plays role as to whether or not echo "no"
runs.
Your second if statement example is also different
if [ 1 -eq $1 ]; then
nocmd "yes"
if [ $? -ne 0 ]; then
echo "no"
fi
else
echo "no"
fi
The echo "no"
after else
doesn't depend on what happens to nocmd
as in the chaining of logical operators. Sure you still do the echo "no"
part after doing nocmd
, but here its exit status isn't grouped together with the whole if
portion to which it belongs.
edited Jan 30 at 17:29
answered Jan 30 at 17:20
Sergiy Kolodyazhnyy
7,63311547
7,63311547
add a comment |Â
add a comment |Â
4
It's no strange thing there, when you ran with
./ddd.sh 0
this part will check[ 1 -eq $1 ]
it's not true (false) (1!=0), so this part won't run&& nocmd "yes"
and this part will run|| echo "no"
, but when it's true1=1
it will execute&& nocmd "yes"
part and since shell doesn't recognizenocmd
command, it's reported error.... command not found
and again second part will run|| echo "no"
.â Ã±ÃÂsýù÷
Jan 30 at 17:00