Understanding boolean operators in bash script [duplicate]
This question already has an answer here:
Invert boolean variable
5 answers
phone_missing=false
echo "missing $phone_missing"
if [ ! $phone_missing ]
then
echo "Lost phone at $readabletime"
$phone_missing=true
fi
I just can't understand this.
The line
echo "missing $phone_missing"
echos missing false
, I would expect the statement
if [ ! $phone_missing ]
to be true and enter the if
clause, but it doesn't? What am I missing here!?
bash scripting
marked as duplicate by Rui F Ribeiro, mosvy, Kusalananda
StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;
$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');
$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
5 hours ago
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 |
This question already has an answer here:
Invert boolean variable
5 answers
phone_missing=false
echo "missing $phone_missing"
if [ ! $phone_missing ]
then
echo "Lost phone at $readabletime"
$phone_missing=true
fi
I just can't understand this.
The line
echo "missing $phone_missing"
echos missing false
, I would expect the statement
if [ ! $phone_missing ]
to be true and enter the if
clause, but it doesn't? What am I missing here!?
bash scripting
marked as duplicate by Rui F Ribeiro, mosvy, Kusalananda
StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;
$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');
$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
5 hours ago
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 |
This question already has an answer here:
Invert boolean variable
5 answers
phone_missing=false
echo "missing $phone_missing"
if [ ! $phone_missing ]
then
echo "Lost phone at $readabletime"
$phone_missing=true
fi
I just can't understand this.
The line
echo "missing $phone_missing"
echos missing false
, I would expect the statement
if [ ! $phone_missing ]
to be true and enter the if
clause, but it doesn't? What am I missing here!?
bash scripting
This question already has an answer here:
Invert boolean variable
5 answers
phone_missing=false
echo "missing $phone_missing"
if [ ! $phone_missing ]
then
echo "Lost phone at $readabletime"
$phone_missing=true
fi
I just can't understand this.
The line
echo "missing $phone_missing"
echos missing false
, I would expect the statement
if [ ! $phone_missing ]
to be true and enter the if
clause, but it doesn't? What am I missing here!?
This question already has an answer here:
Invert boolean variable
5 answers
bash scripting
bash scripting
edited 10 hours ago
Rui F Ribeiro
41.3k1481140
41.3k1481140
asked Dec 19 '13 at 18:31
ascoasco
182116
182116
marked as duplicate by Rui F Ribeiro, mosvy, Kusalananda
StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;
$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');
$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
5 hours ago
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 Rui F Ribeiro, mosvy, Kusalananda
StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;
$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');
$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
5 hours ago
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 |
add a comment |
7 Answers
7
active
oldest
votes
$phone_missing is a string that happens to contain "false". And a non-empty string evaluates to true. See also http://www.linuxintro.org/wiki/Babe#empty_strings
Ah alright. I would have declared that variable as boolean (at least not with the declare word) but the ash console won't let me. I also don't want to compare Strings. How is this done right?
– asco
Dec 19 '13 at 18:57
1
stackoverflow.com/questions/2953646/…, but take care: this guy EXECUTES a string variable, and as well false as true are unix commands.
– Thorsten Staerk
Dec 19 '13 at 19:01
add a comment |
I often use "true" and "false" since they are also commands that merely return success and failure respectively. Then you can do
if "$phone_missing"; then ...
add a comment |
Here's one way to do this, while retaining the true/false values.
phone_missing=false
if [ "$phone_missing" != false ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
if [ "$phone_missing" == true ]; then
echo "phone_missing is true."
fi
The double quotes around $phone_missing
are to protect against the case where variable phone_missing
is not defined at all. Another common idiom to ward against this is [ x$phone_missing != xfalse ]
, but the quotes seem more natural to me.
The hint is in the bash
help page for test
:
STRING True if string is not empty.
...
! EXPR True if expr is false.
So, basically [ $foo ]
will be true if $foo
is non-empty. Not true or false, just non-empty. [ ! $foo ]
is true if $foo is empty or undefined.
You could always change your code to just set phone_missing
to a non-empty value, which will denote true. If phone_missing
is unset (or empty — phone_missing=""
), it will be false. Otherwise, you should be using the string testing operators (=
and !=
).
The other slight issue is the assignment. You have it as $phone_missing=true
, whereas it should be phone_missing=true
(no dollar sign).
Sorry if this is a bit dense, it's because I am. It's been a long day. :)
add a comment |
I would have done this as a comment to support James Ko but didn't have the rep to comment or publicly up vote.
The issue here is that the brackets are notation for doing a comparison test such as value or string equality.
String truthiness in bash for an empty string is ""
(empty string) evaluates to false (return value 1) and any non empty string "false" "true" or "bob's your uncle" evaluates to true (return value 0).
You can prove this to yourself with:
if [ "foo" ]; then
echo true is $?;
else
echo false is $?;
fi
The $?
above is a special variable that holds the last commands exit status (0 success, and any > 0 for error code) and will output true is 0
. You can replace "foo"
with anything you want and the result will be the same except if you replace it with an empty string ""
or ''
in which case it will evaluate the else condition and output false is 1
.
When using the brackets the internal statement such as ! $phone_missing is evaluated and then returns a 0
for true or 1
for false to the if control statement. Since the bracket evaluates string and value comparisons the $phone_missing is first expanded to the non empty string "false" which is evaluated by the as non empty string (or true) and then the ! inverts the result which results in the if statement getting a false (or return value 1) and it skips the conditional body executing the else statement if present.
As James Ko said the notation would be to just pass the variable holding your 'boolean' to the if control statement. Note that in bash a boolean true and false must be lower case as in:
bool_true=true
bool_false=false
Any other case will evaluate as strings and not boolean.
So using your example and James Ko's answer it would be:
phone_missing=false
echo "missing $phone_missing"
if ! $phone_missing
then
echo "Lost phone at $readabletime"
$phone_missing=true
fi
or as I prefer for readability (syntactically the same and James Ko's)
phone_missing=false
echo "missing $phone_missing"
if ( ! $phone_missing ); then
echo "Lost phone at $readabletime"
$phone_missing=true
fi
Other answers such as by Alexios are literally checking the string content. So that either of the following would result in false:
phone_missing=false
if [ "$phone_missing" != false ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
if [ "$phone_missing" == true ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
if [ "$phone_missing" == Bobs_your_uncle ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
add a comment |
Other answers gave you solution, but I will explain what was wrong with the original thinking.
Bash variables don't have types, so there's no such thing as a boolean variable or value like true or false. Basically all bash variables are just strings.
When you test a variable/string in bash without specifying the type of test (-n
or -z
), it will default to a -n
(nonzero length string) test.
So [ "$var" ]
is equivalent to [ -n "$var" ]
. As long as $var
contains at least 1 character, it was evaluate to true.
Since you negated the expression, [ ! "$var" ]
is equivalent to [ ! -n "$var" ]
. So if $var
contains at least 1 character, then the expression is false.
Since false
(which is just a string) contains 5 characters, the expression is false. If doesn't matter what string you set phone_missing
to (true
, 0, 1), the expression will always be false
because is phone_missing
is nonzero length. The only way to make it true
is phone_missing=""
since that is zero length.
add a comment |
Don't use string for boolean. Use integer.
Input:
val=1
((val)) && echo "true" || echo "false"
val=0
((val)) && echo "true" || echo "false"
Output:
true
false
Source:
((expression))
The expression is evaluated according to the rules described below under ARITHMETIC EVALUATION. If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1. This is exactly equivalent to let "expression".
add a comment |
The correct syntax is if ! $bool; then [statements]; fi
.
Example:
bool=false
if ! $bool; then
echo "This is correct!"
fi
if [ ! $bool ]; then
echo "This is wrong!"
fi
Output: This is correct!
There’s a kernel of truth in your answer, but, lacking any explanation, it causes more confusion than it remedies. Also, it is little more than a repeat of one of the previous answers. If you don’t want your answer to be removed, explain why it is right.
– G-Man
May 24 '15 at 6:17
add a comment |
7 Answers
7
active
oldest
votes
7 Answers
7
active
oldest
votes
active
oldest
votes
active
oldest
votes
$phone_missing is a string that happens to contain "false". And a non-empty string evaluates to true. See also http://www.linuxintro.org/wiki/Babe#empty_strings
Ah alright. I would have declared that variable as boolean (at least not with the declare word) but the ash console won't let me. I also don't want to compare Strings. How is this done right?
– asco
Dec 19 '13 at 18:57
1
stackoverflow.com/questions/2953646/…, but take care: this guy EXECUTES a string variable, and as well false as true are unix commands.
– Thorsten Staerk
Dec 19 '13 at 19:01
add a comment |
$phone_missing is a string that happens to contain "false". And a non-empty string evaluates to true. See also http://www.linuxintro.org/wiki/Babe#empty_strings
Ah alright. I would have declared that variable as boolean (at least not with the declare word) but the ash console won't let me. I also don't want to compare Strings. How is this done right?
– asco
Dec 19 '13 at 18:57
1
stackoverflow.com/questions/2953646/…, but take care: this guy EXECUTES a string variable, and as well false as true are unix commands.
– Thorsten Staerk
Dec 19 '13 at 19:01
add a comment |
$phone_missing is a string that happens to contain "false". And a non-empty string evaluates to true. See also http://www.linuxintro.org/wiki/Babe#empty_strings
$phone_missing is a string that happens to contain "false". And a non-empty string evaluates to true. See also http://www.linuxintro.org/wiki/Babe#empty_strings
edited May 24 '15 at 7:35
answered Dec 19 '13 at 18:46
Thorsten StaerkThorsten Staerk
2,26411323
2,26411323
Ah alright. I would have declared that variable as boolean (at least not with the declare word) but the ash console won't let me. I also don't want to compare Strings. How is this done right?
– asco
Dec 19 '13 at 18:57
1
stackoverflow.com/questions/2953646/…, but take care: this guy EXECUTES a string variable, and as well false as true are unix commands.
– Thorsten Staerk
Dec 19 '13 at 19:01
add a comment |
Ah alright. I would have declared that variable as boolean (at least not with the declare word) but the ash console won't let me. I also don't want to compare Strings. How is this done right?
– asco
Dec 19 '13 at 18:57
1
stackoverflow.com/questions/2953646/…, but take care: this guy EXECUTES a string variable, and as well false as true are unix commands.
– Thorsten Staerk
Dec 19 '13 at 19:01
Ah alright. I would have declared that variable as boolean (at least not with the declare word) but the ash console won't let me. I also don't want to compare Strings. How is this done right?
– asco
Dec 19 '13 at 18:57
Ah alright. I would have declared that variable as boolean (at least not with the declare word) but the ash console won't let me. I also don't want to compare Strings. How is this done right?
– asco
Dec 19 '13 at 18:57
1
1
stackoverflow.com/questions/2953646/…, but take care: this guy EXECUTES a string variable, and as well false as true are unix commands.
– Thorsten Staerk
Dec 19 '13 at 19:01
stackoverflow.com/questions/2953646/…, but take care: this guy EXECUTES a string variable, and as well false as true are unix commands.
– Thorsten Staerk
Dec 19 '13 at 19:01
add a comment |
I often use "true" and "false" since they are also commands that merely return success and failure respectively. Then you can do
if "$phone_missing"; then ...
add a comment |
I often use "true" and "false" since they are also commands that merely return success and failure respectively. Then you can do
if "$phone_missing"; then ...
add a comment |
I often use "true" and "false" since they are also commands that merely return success and failure respectively. Then you can do
if "$phone_missing"; then ...
I often use "true" and "false" since they are also commands that merely return success and failure respectively. Then you can do
if "$phone_missing"; then ...
edited Dec 20 '13 at 0:26
Stéphane Chazelas
309k57582942
309k57582942
answered Dec 19 '13 at 18:58
glenn jackmanglenn jackman
52.2k572112
52.2k572112
add a comment |
add a comment |
Here's one way to do this, while retaining the true/false values.
phone_missing=false
if [ "$phone_missing" != false ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
if [ "$phone_missing" == true ]; then
echo "phone_missing is true."
fi
The double quotes around $phone_missing
are to protect against the case where variable phone_missing
is not defined at all. Another common idiom to ward against this is [ x$phone_missing != xfalse ]
, but the quotes seem more natural to me.
The hint is in the bash
help page for test
:
STRING True if string is not empty.
...
! EXPR True if expr is false.
So, basically [ $foo ]
will be true if $foo
is non-empty. Not true or false, just non-empty. [ ! $foo ]
is true if $foo is empty or undefined.
You could always change your code to just set phone_missing
to a non-empty value, which will denote true. If phone_missing
is unset (or empty — phone_missing=""
), it will be false. Otherwise, you should be using the string testing operators (=
and !=
).
The other slight issue is the assignment. You have it as $phone_missing=true
, whereas it should be phone_missing=true
(no dollar sign).
Sorry if this is a bit dense, it's because I am. It's been a long day. :)
add a comment |
Here's one way to do this, while retaining the true/false values.
phone_missing=false
if [ "$phone_missing" != false ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
if [ "$phone_missing" == true ]; then
echo "phone_missing is true."
fi
The double quotes around $phone_missing
are to protect against the case where variable phone_missing
is not defined at all. Another common idiom to ward against this is [ x$phone_missing != xfalse ]
, but the quotes seem more natural to me.
The hint is in the bash
help page for test
:
STRING True if string is not empty.
...
! EXPR True if expr is false.
So, basically [ $foo ]
will be true if $foo
is non-empty. Not true or false, just non-empty. [ ! $foo ]
is true if $foo is empty or undefined.
You could always change your code to just set phone_missing
to a non-empty value, which will denote true. If phone_missing
is unset (or empty — phone_missing=""
), it will be false. Otherwise, you should be using the string testing operators (=
and !=
).
The other slight issue is the assignment. You have it as $phone_missing=true
, whereas it should be phone_missing=true
(no dollar sign).
Sorry if this is a bit dense, it's because I am. It's been a long day. :)
add a comment |
Here's one way to do this, while retaining the true/false values.
phone_missing=false
if [ "$phone_missing" != false ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
if [ "$phone_missing" == true ]; then
echo "phone_missing is true."
fi
The double quotes around $phone_missing
are to protect against the case where variable phone_missing
is not defined at all. Another common idiom to ward against this is [ x$phone_missing != xfalse ]
, but the quotes seem more natural to me.
The hint is in the bash
help page for test
:
STRING True if string is not empty.
...
! EXPR True if expr is false.
So, basically [ $foo ]
will be true if $foo
is non-empty. Not true or false, just non-empty. [ ! $foo ]
is true if $foo is empty or undefined.
You could always change your code to just set phone_missing
to a non-empty value, which will denote true. If phone_missing
is unset (or empty — phone_missing=""
), it will be false. Otherwise, you should be using the string testing operators (=
and !=
).
The other slight issue is the assignment. You have it as $phone_missing=true
, whereas it should be phone_missing=true
(no dollar sign).
Sorry if this is a bit dense, it's because I am. It's been a long day. :)
Here's one way to do this, while retaining the true/false values.
phone_missing=false
if [ "$phone_missing" != false ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
if [ "$phone_missing" == true ]; then
echo "phone_missing is true."
fi
The double quotes around $phone_missing
are to protect against the case where variable phone_missing
is not defined at all. Another common idiom to ward against this is [ x$phone_missing != xfalse ]
, but the quotes seem more natural to me.
The hint is in the bash
help page for test
:
STRING True if string is not empty.
...
! EXPR True if expr is false.
So, basically [ $foo ]
will be true if $foo
is non-empty. Not true or false, just non-empty. [ ! $foo ]
is true if $foo is empty or undefined.
You could always change your code to just set phone_missing
to a non-empty value, which will denote true. If phone_missing
is unset (or empty — phone_missing=""
), it will be false. Otherwise, you should be using the string testing operators (=
and !=
).
The other slight issue is the assignment. You have it as $phone_missing=true
, whereas it should be phone_missing=true
(no dollar sign).
Sorry if this is a bit dense, it's because I am. It's been a long day. :)
edited Nov 7 '14 at 17:31
Ramesh
23.8k34104186
23.8k34104186
answered Dec 19 '13 at 20:54
AlexiosAlexios
14.5k14966
14.5k14966
add a comment |
add a comment |
I would have done this as a comment to support James Ko but didn't have the rep to comment or publicly up vote.
The issue here is that the brackets are notation for doing a comparison test such as value or string equality.
String truthiness in bash for an empty string is ""
(empty string) evaluates to false (return value 1) and any non empty string "false" "true" or "bob's your uncle" evaluates to true (return value 0).
You can prove this to yourself with:
if [ "foo" ]; then
echo true is $?;
else
echo false is $?;
fi
The $?
above is a special variable that holds the last commands exit status (0 success, and any > 0 for error code) and will output true is 0
. You can replace "foo"
with anything you want and the result will be the same except if you replace it with an empty string ""
or ''
in which case it will evaluate the else condition and output false is 1
.
When using the brackets the internal statement such as ! $phone_missing is evaluated and then returns a 0
for true or 1
for false to the if control statement. Since the bracket evaluates string and value comparisons the $phone_missing is first expanded to the non empty string "false" which is evaluated by the as non empty string (or true) and then the ! inverts the result which results in the if statement getting a false (or return value 1) and it skips the conditional body executing the else statement if present.
As James Ko said the notation would be to just pass the variable holding your 'boolean' to the if control statement. Note that in bash a boolean true and false must be lower case as in:
bool_true=true
bool_false=false
Any other case will evaluate as strings and not boolean.
So using your example and James Ko's answer it would be:
phone_missing=false
echo "missing $phone_missing"
if ! $phone_missing
then
echo "Lost phone at $readabletime"
$phone_missing=true
fi
or as I prefer for readability (syntactically the same and James Ko's)
phone_missing=false
echo "missing $phone_missing"
if ( ! $phone_missing ); then
echo "Lost phone at $readabletime"
$phone_missing=true
fi
Other answers such as by Alexios are literally checking the string content. So that either of the following would result in false:
phone_missing=false
if [ "$phone_missing" != false ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
if [ "$phone_missing" == true ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
if [ "$phone_missing" == Bobs_your_uncle ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
add a comment |
I would have done this as a comment to support James Ko but didn't have the rep to comment or publicly up vote.
The issue here is that the brackets are notation for doing a comparison test such as value or string equality.
String truthiness in bash for an empty string is ""
(empty string) evaluates to false (return value 1) and any non empty string "false" "true" or "bob's your uncle" evaluates to true (return value 0).
You can prove this to yourself with:
if [ "foo" ]; then
echo true is $?;
else
echo false is $?;
fi
The $?
above is a special variable that holds the last commands exit status (0 success, and any > 0 for error code) and will output true is 0
. You can replace "foo"
with anything you want and the result will be the same except if you replace it with an empty string ""
or ''
in which case it will evaluate the else condition and output false is 1
.
When using the brackets the internal statement such as ! $phone_missing is evaluated and then returns a 0
for true or 1
for false to the if control statement. Since the bracket evaluates string and value comparisons the $phone_missing is first expanded to the non empty string "false" which is evaluated by the as non empty string (or true) and then the ! inverts the result which results in the if statement getting a false (or return value 1) and it skips the conditional body executing the else statement if present.
As James Ko said the notation would be to just pass the variable holding your 'boolean' to the if control statement. Note that in bash a boolean true and false must be lower case as in:
bool_true=true
bool_false=false
Any other case will evaluate as strings and not boolean.
So using your example and James Ko's answer it would be:
phone_missing=false
echo "missing $phone_missing"
if ! $phone_missing
then
echo "Lost phone at $readabletime"
$phone_missing=true
fi
or as I prefer for readability (syntactically the same and James Ko's)
phone_missing=false
echo "missing $phone_missing"
if ( ! $phone_missing ); then
echo "Lost phone at $readabletime"
$phone_missing=true
fi
Other answers such as by Alexios are literally checking the string content. So that either of the following would result in false:
phone_missing=false
if [ "$phone_missing" != false ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
if [ "$phone_missing" == true ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
if [ "$phone_missing" == Bobs_your_uncle ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
add a comment |
I would have done this as a comment to support James Ko but didn't have the rep to comment or publicly up vote.
The issue here is that the brackets are notation for doing a comparison test such as value or string equality.
String truthiness in bash for an empty string is ""
(empty string) evaluates to false (return value 1) and any non empty string "false" "true" or "bob's your uncle" evaluates to true (return value 0).
You can prove this to yourself with:
if [ "foo" ]; then
echo true is $?;
else
echo false is $?;
fi
The $?
above is a special variable that holds the last commands exit status (0 success, and any > 0 for error code) and will output true is 0
. You can replace "foo"
with anything you want and the result will be the same except if you replace it with an empty string ""
or ''
in which case it will evaluate the else condition and output false is 1
.
When using the brackets the internal statement such as ! $phone_missing is evaluated and then returns a 0
for true or 1
for false to the if control statement. Since the bracket evaluates string and value comparisons the $phone_missing is first expanded to the non empty string "false" which is evaluated by the as non empty string (or true) and then the ! inverts the result which results in the if statement getting a false (or return value 1) and it skips the conditional body executing the else statement if present.
As James Ko said the notation would be to just pass the variable holding your 'boolean' to the if control statement. Note that in bash a boolean true and false must be lower case as in:
bool_true=true
bool_false=false
Any other case will evaluate as strings and not boolean.
So using your example and James Ko's answer it would be:
phone_missing=false
echo "missing $phone_missing"
if ! $phone_missing
then
echo "Lost phone at $readabletime"
$phone_missing=true
fi
or as I prefer for readability (syntactically the same and James Ko's)
phone_missing=false
echo "missing $phone_missing"
if ( ! $phone_missing ); then
echo "Lost phone at $readabletime"
$phone_missing=true
fi
Other answers such as by Alexios are literally checking the string content. So that either of the following would result in false:
phone_missing=false
if [ "$phone_missing" != false ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
if [ "$phone_missing" == true ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
if [ "$phone_missing" == Bobs_your_uncle ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
I would have done this as a comment to support James Ko but didn't have the rep to comment or publicly up vote.
The issue here is that the brackets are notation for doing a comparison test such as value or string equality.
String truthiness in bash for an empty string is ""
(empty string) evaluates to false (return value 1) and any non empty string "false" "true" or "bob's your uncle" evaluates to true (return value 0).
You can prove this to yourself with:
if [ "foo" ]; then
echo true is $?;
else
echo false is $?;
fi
The $?
above is a special variable that holds the last commands exit status (0 success, and any > 0 for error code) and will output true is 0
. You can replace "foo"
with anything you want and the result will be the same except if you replace it with an empty string ""
or ''
in which case it will evaluate the else condition and output false is 1
.
When using the brackets the internal statement such as ! $phone_missing is evaluated and then returns a 0
for true or 1
for false to the if control statement. Since the bracket evaluates string and value comparisons the $phone_missing is first expanded to the non empty string "false" which is evaluated by the as non empty string (or true) and then the ! inverts the result which results in the if statement getting a false (or return value 1) and it skips the conditional body executing the else statement if present.
As James Ko said the notation would be to just pass the variable holding your 'boolean' to the if control statement. Note that in bash a boolean true and false must be lower case as in:
bool_true=true
bool_false=false
Any other case will evaluate as strings and not boolean.
So using your example and James Ko's answer it would be:
phone_missing=false
echo "missing $phone_missing"
if ! $phone_missing
then
echo "Lost phone at $readabletime"
$phone_missing=true
fi
or as I prefer for readability (syntactically the same and James Ko's)
phone_missing=false
echo "missing $phone_missing"
if ( ! $phone_missing ); then
echo "Lost phone at $readabletime"
$phone_missing=true
fi
Other answers such as by Alexios are literally checking the string content. So that either of the following would result in false:
phone_missing=false
if [ "$phone_missing" != false ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
if [ "$phone_missing" == true ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
if [ "$phone_missing" == Bobs_your_uncle ]; then
echo "phone_missing is not 'false' (but may be non-true, too)"
fi
answered Sep 14 '15 at 18:26
DVSDVS
101
101
add a comment |
add a comment |
Other answers gave you solution, but I will explain what was wrong with the original thinking.
Bash variables don't have types, so there's no such thing as a boolean variable or value like true or false. Basically all bash variables are just strings.
When you test a variable/string in bash without specifying the type of test (-n
or -z
), it will default to a -n
(nonzero length string) test.
So [ "$var" ]
is equivalent to [ -n "$var" ]
. As long as $var
contains at least 1 character, it was evaluate to true.
Since you negated the expression, [ ! "$var" ]
is equivalent to [ ! -n "$var" ]
. So if $var
contains at least 1 character, then the expression is false.
Since false
(which is just a string) contains 5 characters, the expression is false. If doesn't matter what string you set phone_missing
to (true
, 0, 1), the expression will always be false
because is phone_missing
is nonzero length. The only way to make it true
is phone_missing=""
since that is zero length.
add a comment |
Other answers gave you solution, but I will explain what was wrong with the original thinking.
Bash variables don't have types, so there's no such thing as a boolean variable or value like true or false. Basically all bash variables are just strings.
When you test a variable/string in bash without specifying the type of test (-n
or -z
), it will default to a -n
(nonzero length string) test.
So [ "$var" ]
is equivalent to [ -n "$var" ]
. As long as $var
contains at least 1 character, it was evaluate to true.
Since you negated the expression, [ ! "$var" ]
is equivalent to [ ! -n "$var" ]
. So if $var
contains at least 1 character, then the expression is false.
Since false
(which is just a string) contains 5 characters, the expression is false. If doesn't matter what string you set phone_missing
to (true
, 0, 1), the expression will always be false
because is phone_missing
is nonzero length. The only way to make it true
is phone_missing=""
since that is zero length.
add a comment |
Other answers gave you solution, but I will explain what was wrong with the original thinking.
Bash variables don't have types, so there's no such thing as a boolean variable or value like true or false. Basically all bash variables are just strings.
When you test a variable/string in bash without specifying the type of test (-n
or -z
), it will default to a -n
(nonzero length string) test.
So [ "$var" ]
is equivalent to [ -n "$var" ]
. As long as $var
contains at least 1 character, it was evaluate to true.
Since you negated the expression, [ ! "$var" ]
is equivalent to [ ! -n "$var" ]
. So if $var
contains at least 1 character, then the expression is false.
Since false
(which is just a string) contains 5 characters, the expression is false. If doesn't matter what string you set phone_missing
to (true
, 0, 1), the expression will always be false
because is phone_missing
is nonzero length. The only way to make it true
is phone_missing=""
since that is zero length.
Other answers gave you solution, but I will explain what was wrong with the original thinking.
Bash variables don't have types, so there's no such thing as a boolean variable or value like true or false. Basically all bash variables are just strings.
When you test a variable/string in bash without specifying the type of test (-n
or -z
), it will default to a -n
(nonzero length string) test.
So [ "$var" ]
is equivalent to [ -n "$var" ]
. As long as $var
contains at least 1 character, it was evaluate to true.
Since you negated the expression, [ ! "$var" ]
is equivalent to [ ! -n "$var" ]
. So if $var
contains at least 1 character, then the expression is false.
Since false
(which is just a string) contains 5 characters, the expression is false. If doesn't matter what string you set phone_missing
to (true
, 0, 1), the expression will always be false
because is phone_missing
is nonzero length. The only way to make it true
is phone_missing=""
since that is zero length.
answered Jun 1 '18 at 3:47
wisbuckywisbucky
678810
678810
add a comment |
add a comment |
Don't use string for boolean. Use integer.
Input:
val=1
((val)) && echo "true" || echo "false"
val=0
((val)) && echo "true" || echo "false"
Output:
true
false
Source:
((expression))
The expression is evaluated according to the rules described below under ARITHMETIC EVALUATION. If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1. This is exactly equivalent to let "expression".
add a comment |
Don't use string for boolean. Use integer.
Input:
val=1
((val)) && echo "true" || echo "false"
val=0
((val)) && echo "true" || echo "false"
Output:
true
false
Source:
((expression))
The expression is evaluated according to the rules described below under ARITHMETIC EVALUATION. If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1. This is exactly equivalent to let "expression".
add a comment |
Don't use string for boolean. Use integer.
Input:
val=1
((val)) && echo "true" || echo "false"
val=0
((val)) && echo "true" || echo "false"
Output:
true
false
Source:
((expression))
The expression is evaluated according to the rules described below under ARITHMETIC EVALUATION. If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1. This is exactly equivalent to let "expression".
Don't use string for boolean. Use integer.
Input:
val=1
((val)) && echo "true" || echo "false"
val=0
((val)) && echo "true" || echo "false"
Output:
true
false
Source:
((expression))
The expression is evaluated according to the rules described below under ARITHMETIC EVALUATION. If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1. This is exactly equivalent to let "expression".
answered Jul 30 '18 at 18:19
CykerCyker
1,50521531
1,50521531
add a comment |
add a comment |
The correct syntax is if ! $bool; then [statements]; fi
.
Example:
bool=false
if ! $bool; then
echo "This is correct!"
fi
if [ ! $bool ]; then
echo "This is wrong!"
fi
Output: This is correct!
There’s a kernel of truth in your answer, but, lacking any explanation, it causes more confusion than it remedies. Also, it is little more than a repeat of one of the previous answers. If you don’t want your answer to be removed, explain why it is right.
– G-Man
May 24 '15 at 6:17
add a comment |
The correct syntax is if ! $bool; then [statements]; fi
.
Example:
bool=false
if ! $bool; then
echo "This is correct!"
fi
if [ ! $bool ]; then
echo "This is wrong!"
fi
Output: This is correct!
There’s a kernel of truth in your answer, but, lacking any explanation, it causes more confusion than it remedies. Also, it is little more than a repeat of one of the previous answers. If you don’t want your answer to be removed, explain why it is right.
– G-Man
May 24 '15 at 6:17
add a comment |
The correct syntax is if ! $bool; then [statements]; fi
.
Example:
bool=false
if ! $bool; then
echo "This is correct!"
fi
if [ ! $bool ]; then
echo "This is wrong!"
fi
Output: This is correct!
The correct syntax is if ! $bool; then [statements]; fi
.
Example:
bool=false
if ! $bool; then
echo "This is correct!"
fi
if [ ! $bool ]; then
echo "This is wrong!"
fi
Output: This is correct!
answered May 24 '15 at 5:45
James KoJames Ko
1403
1403
There’s a kernel of truth in your answer, but, lacking any explanation, it causes more confusion than it remedies. Also, it is little more than a repeat of one of the previous answers. If you don’t want your answer to be removed, explain why it is right.
– G-Man
May 24 '15 at 6:17
add a comment |
There’s a kernel of truth in your answer, but, lacking any explanation, it causes more confusion than it remedies. Also, it is little more than a repeat of one of the previous answers. If you don’t want your answer to be removed, explain why it is right.
– G-Man
May 24 '15 at 6:17
There’s a kernel of truth in your answer, but, lacking any explanation, it causes more confusion than it remedies. Also, it is little more than a repeat of one of the previous answers. If you don’t want your answer to be removed, explain why it is right.
– G-Man
May 24 '15 at 6:17
There’s a kernel of truth in your answer, but, lacking any explanation, it causes more confusion than it remedies. Also, it is little more than a repeat of one of the previous answers. If you don’t want your answer to be removed, explain why it is right.
– G-Man
May 24 '15 at 6:17
add a comment |