bash - What do the brackets in if-statements do? [duplicate]
Clash Royale CLAN TAG#URR8PPP
up vote
3
down vote
favorite
This question already has an answer here:
What is the difference between the Bash operators [[ vs [ vs ( vs ((?
6 answers
Perhaps this applies to more than just bash, but I am confused about the role of brackets in if-statements. Most examples seem to have the following format
if [ expression ]; then
#do stuff
fi
But this doesn't always work for me. For example I have the following script test.sh
:
#!/bin/bash
flag=False
if ! $flag; then
echo "No brackets: Flag is $flag"
fi
if [ ! $flag ]; then
echo "With brackets: Flag is $flag"
fi
echo "The end."
Which prints
$ ./test.sh
No brackets: Flag is False
The end.
So the statement using brackets is either ignored or it evaluates to False. Why does this happen? What do the brackets do?
I've also seen double brackets. How are those used?
--
Edit: the questions claimed as duplicates (this and this) answer only a small part of this question. I'm still unclear why the syntax with brackets would fail (it seems to me that test ! false
should evaluate to true
) and why the syntax without brackets succeeds (although, as @ilkkachu mentions in the comment, it seems like it should actually fail as well?).
linux bash test control-flow
marked as duplicate by Sergiy Kolodyazhnyy, elbarna, Thomas, RalfFriedl, Romeo Ninov yesterday
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.
|
show 2 more comments
up vote
3
down vote
favorite
This question already has an answer here:
What is the difference between the Bash operators [[ vs [ vs ( vs ((?
6 answers
Perhaps this applies to more than just bash, but I am confused about the role of brackets in if-statements. Most examples seem to have the following format
if [ expression ]; then
#do stuff
fi
But this doesn't always work for me. For example I have the following script test.sh
:
#!/bin/bash
flag=False
if ! $flag; then
echo "No brackets: Flag is $flag"
fi
if [ ! $flag ]; then
echo "With brackets: Flag is $flag"
fi
echo "The end."
Which prints
$ ./test.sh
No brackets: Flag is False
The end.
So the statement using brackets is either ignored or it evaluates to False. Why does this happen? What do the brackets do?
I've also seen double brackets. How are those used?
--
Edit: the questions claimed as duplicates (this and this) answer only a small part of this question. I'm still unclear why the syntax with brackets would fail (it seems to me that test ! false
should evaluate to true
) and why the syntax without brackets succeeds (although, as @ilkkachu mentions in the comment, it seems like it should actually fail as well?).
linux bash test control-flow
marked as duplicate by Sergiy Kolodyazhnyy, elbarna, Thomas, RalfFriedl, Romeo Ninov yesterday
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.
Or unix.stackexchange.com/questions/99185/…
– LittleSmurfie
Jun 7 '17 at 21:51
1
This could be a good reference for you to read over. linuxacademy.com/blog/linux/…
– JayJay
Jun 7 '17 at 21:58
1
flag=False; if ! $flag ; then ...
should give you an error, unless you really have a command calledFalse
. (false
would be standard, however)
– ilkkachu
Jun 7 '17 at 22:33
... for meif [ !$flag ]; then
works (no space between!
and$flag
)
– Michael D.
Jun 12 '17 at 19:48
1
I have googled that if test have 2 arguments and If the first argument is ! (exclamation mark), the expression is true if, and only if, the second argument is null. i found it here
– Krzysztof Stasiak
Jun 12 '17 at 20:11
|
show 2 more comments
up vote
3
down vote
favorite
up vote
3
down vote
favorite
This question already has an answer here:
What is the difference between the Bash operators [[ vs [ vs ( vs ((?
6 answers
Perhaps this applies to more than just bash, but I am confused about the role of brackets in if-statements. Most examples seem to have the following format
if [ expression ]; then
#do stuff
fi
But this doesn't always work for me. For example I have the following script test.sh
:
#!/bin/bash
flag=False
if ! $flag; then
echo "No brackets: Flag is $flag"
fi
if [ ! $flag ]; then
echo "With brackets: Flag is $flag"
fi
echo "The end."
Which prints
$ ./test.sh
No brackets: Flag is False
The end.
So the statement using brackets is either ignored or it evaluates to False. Why does this happen? What do the brackets do?
I've also seen double brackets. How are those used?
--
Edit: the questions claimed as duplicates (this and this) answer only a small part of this question. I'm still unclear why the syntax with brackets would fail (it seems to me that test ! false
should evaluate to true
) and why the syntax without brackets succeeds (although, as @ilkkachu mentions in the comment, it seems like it should actually fail as well?).
linux bash test control-flow
This question already has an answer here:
What is the difference between the Bash operators [[ vs [ vs ( vs ((?
6 answers
Perhaps this applies to more than just bash, but I am confused about the role of brackets in if-statements. Most examples seem to have the following format
if [ expression ]; then
#do stuff
fi
But this doesn't always work for me. For example I have the following script test.sh
:
#!/bin/bash
flag=False
if ! $flag; then
echo "No brackets: Flag is $flag"
fi
if [ ! $flag ]; then
echo "With brackets: Flag is $flag"
fi
echo "The end."
Which prints
$ ./test.sh
No brackets: Flag is False
The end.
So the statement using brackets is either ignored or it evaluates to False. Why does this happen? What do the brackets do?
I've also seen double brackets. How are those used?
--
Edit: the questions claimed as duplicates (this and this) answer only a small part of this question. I'm still unclear why the syntax with brackets would fail (it seems to me that test ! false
should evaluate to true
) and why the syntax without brackets succeeds (although, as @ilkkachu mentions in the comment, it seems like it should actually fail as well?).
This question already has an answer here:
What is the difference between the Bash operators [[ vs [ vs ( vs ((?
6 answers
linux bash test control-flow
linux bash test control-flow
edited Jan 23 at 5:00
Tomasz
8,72552862
8,72552862
asked Jun 7 '17 at 21:40
dkv
22728
22728
marked as duplicate by Sergiy Kolodyazhnyy, elbarna, Thomas, RalfFriedl, Romeo Ninov yesterday
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 Sergiy Kolodyazhnyy, elbarna, Thomas, RalfFriedl, Romeo Ninov yesterday
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.
Or unix.stackexchange.com/questions/99185/…
– LittleSmurfie
Jun 7 '17 at 21:51
1
This could be a good reference for you to read over. linuxacademy.com/blog/linux/…
– JayJay
Jun 7 '17 at 21:58
1
flag=False; if ! $flag ; then ...
should give you an error, unless you really have a command calledFalse
. (false
would be standard, however)
– ilkkachu
Jun 7 '17 at 22:33
... for meif [ !$flag ]; then
works (no space between!
and$flag
)
– Michael D.
Jun 12 '17 at 19:48
1
I have googled that if test have 2 arguments and If the first argument is ! (exclamation mark), the expression is true if, and only if, the second argument is null. i found it here
– Krzysztof Stasiak
Jun 12 '17 at 20:11
|
show 2 more comments
Or unix.stackexchange.com/questions/99185/…
– LittleSmurfie
Jun 7 '17 at 21:51
1
This could be a good reference for you to read over. linuxacademy.com/blog/linux/…
– JayJay
Jun 7 '17 at 21:58
1
flag=False; if ! $flag ; then ...
should give you an error, unless you really have a command calledFalse
. (false
would be standard, however)
– ilkkachu
Jun 7 '17 at 22:33
... for meif [ !$flag ]; then
works (no space between!
and$flag
)
– Michael D.
Jun 12 '17 at 19:48
1
I have googled that if test have 2 arguments and If the first argument is ! (exclamation mark), the expression is true if, and only if, the second argument is null. i found it here
– Krzysztof Stasiak
Jun 12 '17 at 20:11
Or unix.stackexchange.com/questions/99185/…
– LittleSmurfie
Jun 7 '17 at 21:51
Or unix.stackexchange.com/questions/99185/…
– LittleSmurfie
Jun 7 '17 at 21:51
1
1
This could be a good reference for you to read over. linuxacademy.com/blog/linux/…
– JayJay
Jun 7 '17 at 21:58
This could be a good reference for you to read over. linuxacademy.com/blog/linux/…
– JayJay
Jun 7 '17 at 21:58
1
1
flag=False; if ! $flag ; then ...
should give you an error, unless you really have a command called False
. (false
would be standard, however)– ilkkachu
Jun 7 '17 at 22:33
flag=False; if ! $flag ; then ...
should give you an error, unless you really have a command called False
. (false
would be standard, however)– ilkkachu
Jun 7 '17 at 22:33
... for me
if [ !$flag ]; then
works (no space between !
and $flag
)– Michael D.
Jun 12 '17 at 19:48
... for me
if [ !$flag ]; then
works (no space between !
and $flag
)– Michael D.
Jun 12 '17 at 19:48
1
1
I have googled that if test have 2 arguments and If the first argument is ! (exclamation mark), the expression is true if, and only if, the second argument is null. i found it here
– Krzysztof Stasiak
Jun 12 '17 at 20:11
I have googled that if test have 2 arguments and If the first argument is ! (exclamation mark), the expression is true if, and only if, the second argument is null. i found it here
– Krzysztof Stasiak
Jun 12 '17 at 20:11
|
show 2 more comments
2 Answers
2
active
oldest
votes
up vote
2
down vote
On any Unix other than those that have case-insensitive filesystems (like macOS), the if
statement
if ! $flag; then
echo "No brackets: Flag is $flag"
fi
would generate the output
bash: False: command not found
No brackets: Flag is False
On macOS, the error would not be generate as the False
command is the same as the standard (external) false
command due to the case-insensitivity of the filesystem.
In either case, the test on ! $flag
is true (but for different reasons), so the text is printed. On most Unices, ! $flag
is true since it runs the False
command, fails, and the failure is negated. On macOS, it runs the external false
utility, which returns false, which is negated.
The second if
statement,
if [ ! $flag ]; then
echo "With brackets: Flag is $flag"
fi
works the same way on any Unix. It calls the [
utility, which is the same as the test
utility (but [
requires a matching ]
as its last operand), with the two arguments !
and False
. By default, test
will return a true value if the string argument has non-zero length, which it has, but it's negated by the !
so test
returns false and the echo
is never executed.
For clarity, it is better to use the -n
test to test for a non-empty string:
if [ -n "$flag" ]; then ...
or -z
to test for an empty string:
if [ -z "$flag" ]; then ...
The quoting of the variable expansions is not important in this particular piece of code as $flag
expands to a single word that is not a filename globbing pattern. In general though, variable expansions should be double quoted to avoid word splitting and filename globbing.
For a discussion about [
vs. [[
, see
- What is the difference between the Bash operators [[ vs [ vs ( vs ((?
Related:
man test
on your system, andhelp test
in anybash
shell.- Why does my shell script choke on whitespace or other special characters?
+1 Case insensitivity by default thankfully came to an end with the introduction of APFS on macOS High Sierra.
– Christopher
2 days ago
@Christopher Hmm... My main disk is still case-insensitive with APFS, but that may be because it's been converted from case-insensitive HFS+ with the Mojave update. BTW, HFS+ had a case-sensitive option too, but the default was case-insensitive.
– Kusalananda
2 days ago
Yes, Sir. True.
– Christopher
2 days ago
Whether$flag
expand to one or more words and which depends on the value of$IFS
. It still doesn't make sense to leave it unquoted when you know$flag
containsFalse
.
– Stéphane Chazelas
2 days ago
@StéphaneChazelas Bash resetsIFS
for new shells, and the variable is not set in the script. How could$flag
be split in multiple words here?
– Kusalananda
yesterday
|
show 1 more comment
up vote
1
down vote
The exact answer is a bit complex. It boils down to understanding that the word false
is both a command and an string (depending on context).
A longer description:
Lets start with the string A_Non_Existing_Command.
str=A_Non_Existing_Command
So, a (In general: please quote variable expansions.)
$ if $str; then echo yes; else echo no; fi
bash: A_Non_Existing_Command: command not found
no
Will print no, as the command executed fails (it doesn't exist) and the else part gets executed. Of course, there is an error message as well (more later).
However, the test command, either test
or [
(read help test
inside bash) will test if:
the length of the string between brackets is non-zero
And, so:
$ if [ "$str" ]; then echo yes; else echo no; fi
yes
Prints a yes (as the string has a non-zero amount of characters (usually bytes)). It doesn't matter that the string is also the name of a non-existing command. In this case the value of the variable is interpreted (evaluated) as an string.
And, of course, the negative test will print no:
$ if [ ! "$str" ]; then echo yes; else echo no; fi
no
Which is exactly equivalent to [ -z "$str" ]
.
Now, changing the str
content to False
and executing the same commands:
$ str=false
$ if "$str" ; then echo yes; else echo no; fi
no
$ if [ "$str" ]; then echo yes; else echo no; fi
yes
$ if [ ! "$str" ]; then echo yes; else echo no; fi
no
If you get the same with str=False
(without errors) is probably because you are in a system with a case-insensitive filesystem (where searching for False will find false without any error).
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
On any Unix other than those that have case-insensitive filesystems (like macOS), the if
statement
if ! $flag; then
echo "No brackets: Flag is $flag"
fi
would generate the output
bash: False: command not found
No brackets: Flag is False
On macOS, the error would not be generate as the False
command is the same as the standard (external) false
command due to the case-insensitivity of the filesystem.
In either case, the test on ! $flag
is true (but for different reasons), so the text is printed. On most Unices, ! $flag
is true since it runs the False
command, fails, and the failure is negated. On macOS, it runs the external false
utility, which returns false, which is negated.
The second if
statement,
if [ ! $flag ]; then
echo "With brackets: Flag is $flag"
fi
works the same way on any Unix. It calls the [
utility, which is the same as the test
utility (but [
requires a matching ]
as its last operand), with the two arguments !
and False
. By default, test
will return a true value if the string argument has non-zero length, which it has, but it's negated by the !
so test
returns false and the echo
is never executed.
For clarity, it is better to use the -n
test to test for a non-empty string:
if [ -n "$flag" ]; then ...
or -z
to test for an empty string:
if [ -z "$flag" ]; then ...
The quoting of the variable expansions is not important in this particular piece of code as $flag
expands to a single word that is not a filename globbing pattern. In general though, variable expansions should be double quoted to avoid word splitting and filename globbing.
For a discussion about [
vs. [[
, see
- What is the difference between the Bash operators [[ vs [ vs ( vs ((?
Related:
man test
on your system, andhelp test
in anybash
shell.- Why does my shell script choke on whitespace or other special characters?
+1 Case insensitivity by default thankfully came to an end with the introduction of APFS on macOS High Sierra.
– Christopher
2 days ago
@Christopher Hmm... My main disk is still case-insensitive with APFS, but that may be because it's been converted from case-insensitive HFS+ with the Mojave update. BTW, HFS+ had a case-sensitive option too, but the default was case-insensitive.
– Kusalananda
2 days ago
Yes, Sir. True.
– Christopher
2 days ago
Whether$flag
expand to one or more words and which depends on the value of$IFS
. It still doesn't make sense to leave it unquoted when you know$flag
containsFalse
.
– Stéphane Chazelas
2 days ago
@StéphaneChazelas Bash resetsIFS
for new shells, and the variable is not set in the script. How could$flag
be split in multiple words here?
– Kusalananda
yesterday
|
show 1 more comment
up vote
2
down vote
On any Unix other than those that have case-insensitive filesystems (like macOS), the if
statement
if ! $flag; then
echo "No brackets: Flag is $flag"
fi
would generate the output
bash: False: command not found
No brackets: Flag is False
On macOS, the error would not be generate as the False
command is the same as the standard (external) false
command due to the case-insensitivity of the filesystem.
In either case, the test on ! $flag
is true (but for different reasons), so the text is printed. On most Unices, ! $flag
is true since it runs the False
command, fails, and the failure is negated. On macOS, it runs the external false
utility, which returns false, which is negated.
The second if
statement,
if [ ! $flag ]; then
echo "With brackets: Flag is $flag"
fi
works the same way on any Unix. It calls the [
utility, which is the same as the test
utility (but [
requires a matching ]
as its last operand), with the two arguments !
and False
. By default, test
will return a true value if the string argument has non-zero length, which it has, but it's negated by the !
so test
returns false and the echo
is never executed.
For clarity, it is better to use the -n
test to test for a non-empty string:
if [ -n "$flag" ]; then ...
or -z
to test for an empty string:
if [ -z "$flag" ]; then ...
The quoting of the variable expansions is not important in this particular piece of code as $flag
expands to a single word that is not a filename globbing pattern. In general though, variable expansions should be double quoted to avoid word splitting and filename globbing.
For a discussion about [
vs. [[
, see
- What is the difference between the Bash operators [[ vs [ vs ( vs ((?
Related:
man test
on your system, andhelp test
in anybash
shell.- Why does my shell script choke on whitespace or other special characters?
+1 Case insensitivity by default thankfully came to an end with the introduction of APFS on macOS High Sierra.
– Christopher
2 days ago
@Christopher Hmm... My main disk is still case-insensitive with APFS, but that may be because it's been converted from case-insensitive HFS+ with the Mojave update. BTW, HFS+ had a case-sensitive option too, but the default was case-insensitive.
– Kusalananda
2 days ago
Yes, Sir. True.
– Christopher
2 days ago
Whether$flag
expand to one or more words and which depends on the value of$IFS
. It still doesn't make sense to leave it unquoted when you know$flag
containsFalse
.
– Stéphane Chazelas
2 days ago
@StéphaneChazelas Bash resetsIFS
for new shells, and the variable is not set in the script. How could$flag
be split in multiple words here?
– Kusalananda
yesterday
|
show 1 more comment
up vote
2
down vote
up vote
2
down vote
On any Unix other than those that have case-insensitive filesystems (like macOS), the if
statement
if ! $flag; then
echo "No brackets: Flag is $flag"
fi
would generate the output
bash: False: command not found
No brackets: Flag is False
On macOS, the error would not be generate as the False
command is the same as the standard (external) false
command due to the case-insensitivity of the filesystem.
In either case, the test on ! $flag
is true (but for different reasons), so the text is printed. On most Unices, ! $flag
is true since it runs the False
command, fails, and the failure is negated. On macOS, it runs the external false
utility, which returns false, which is negated.
The second if
statement,
if [ ! $flag ]; then
echo "With brackets: Flag is $flag"
fi
works the same way on any Unix. It calls the [
utility, which is the same as the test
utility (but [
requires a matching ]
as its last operand), with the two arguments !
and False
. By default, test
will return a true value if the string argument has non-zero length, which it has, but it's negated by the !
so test
returns false and the echo
is never executed.
For clarity, it is better to use the -n
test to test for a non-empty string:
if [ -n "$flag" ]; then ...
or -z
to test for an empty string:
if [ -z "$flag" ]; then ...
The quoting of the variable expansions is not important in this particular piece of code as $flag
expands to a single word that is not a filename globbing pattern. In general though, variable expansions should be double quoted to avoid word splitting and filename globbing.
For a discussion about [
vs. [[
, see
- What is the difference between the Bash operators [[ vs [ vs ( vs ((?
Related:
man test
on your system, andhelp test
in anybash
shell.- Why does my shell script choke on whitespace or other special characters?
On any Unix other than those that have case-insensitive filesystems (like macOS), the if
statement
if ! $flag; then
echo "No brackets: Flag is $flag"
fi
would generate the output
bash: False: command not found
No brackets: Flag is False
On macOS, the error would not be generate as the False
command is the same as the standard (external) false
command due to the case-insensitivity of the filesystem.
In either case, the test on ! $flag
is true (but for different reasons), so the text is printed. On most Unices, ! $flag
is true since it runs the False
command, fails, and the failure is negated. On macOS, it runs the external false
utility, which returns false, which is negated.
The second if
statement,
if [ ! $flag ]; then
echo "With brackets: Flag is $flag"
fi
works the same way on any Unix. It calls the [
utility, which is the same as the test
utility (but [
requires a matching ]
as its last operand), with the two arguments !
and False
. By default, test
will return a true value if the string argument has non-zero length, which it has, but it's negated by the !
so test
returns false and the echo
is never executed.
For clarity, it is better to use the -n
test to test for a non-empty string:
if [ -n "$flag" ]; then ...
or -z
to test for an empty string:
if [ -z "$flag" ]; then ...
The quoting of the variable expansions is not important in this particular piece of code as $flag
expands to a single word that is not a filename globbing pattern. In general though, variable expansions should be double quoted to avoid word splitting and filename globbing.
For a discussion about [
vs. [[
, see
- What is the difference between the Bash operators [[ vs [ vs ( vs ((?
Related:
man test
on your system, andhelp test
in anybash
shell.- Why does my shell script choke on whitespace or other special characters?
edited 2 days ago
answered 2 days ago
Kusalananda
115k15218351
115k15218351
+1 Case insensitivity by default thankfully came to an end with the introduction of APFS on macOS High Sierra.
– Christopher
2 days ago
@Christopher Hmm... My main disk is still case-insensitive with APFS, but that may be because it's been converted from case-insensitive HFS+ with the Mojave update. BTW, HFS+ had a case-sensitive option too, but the default was case-insensitive.
– Kusalananda
2 days ago
Yes, Sir. True.
– Christopher
2 days ago
Whether$flag
expand to one or more words and which depends on the value of$IFS
. It still doesn't make sense to leave it unquoted when you know$flag
containsFalse
.
– Stéphane Chazelas
2 days ago
@StéphaneChazelas Bash resetsIFS
for new shells, and the variable is not set in the script. How could$flag
be split in multiple words here?
– Kusalananda
yesterday
|
show 1 more comment
+1 Case insensitivity by default thankfully came to an end with the introduction of APFS on macOS High Sierra.
– Christopher
2 days ago
@Christopher Hmm... My main disk is still case-insensitive with APFS, but that may be because it's been converted from case-insensitive HFS+ with the Mojave update. BTW, HFS+ had a case-sensitive option too, but the default was case-insensitive.
– Kusalananda
2 days ago
Yes, Sir. True.
– Christopher
2 days ago
Whether$flag
expand to one or more words and which depends on the value of$IFS
. It still doesn't make sense to leave it unquoted when you know$flag
containsFalse
.
– Stéphane Chazelas
2 days ago
@StéphaneChazelas Bash resetsIFS
for new shells, and the variable is not set in the script. How could$flag
be split in multiple words here?
– Kusalananda
yesterday
+1 Case insensitivity by default thankfully came to an end with the introduction of APFS on macOS High Sierra.
– Christopher
2 days ago
+1 Case insensitivity by default thankfully came to an end with the introduction of APFS on macOS High Sierra.
– Christopher
2 days ago
@Christopher Hmm... My main disk is still case-insensitive with APFS, but that may be because it's been converted from case-insensitive HFS+ with the Mojave update. BTW, HFS+ had a case-sensitive option too, but the default was case-insensitive.
– Kusalananda
2 days ago
@Christopher Hmm... My main disk is still case-insensitive with APFS, but that may be because it's been converted from case-insensitive HFS+ with the Mojave update. BTW, HFS+ had a case-sensitive option too, but the default was case-insensitive.
– Kusalananda
2 days ago
Yes, Sir. True.
– Christopher
2 days ago
Yes, Sir. True.
– Christopher
2 days ago
Whether
$flag
expand to one or more words and which depends on the value of $IFS
. It still doesn't make sense to leave it unquoted when you know $flag
contains False
.– Stéphane Chazelas
2 days ago
Whether
$flag
expand to one or more words and which depends on the value of $IFS
. It still doesn't make sense to leave it unquoted when you know $flag
contains False
.– Stéphane Chazelas
2 days ago
@StéphaneChazelas Bash resets
IFS
for new shells, and the variable is not set in the script. How could $flag
be split in multiple words here?– Kusalananda
yesterday
@StéphaneChazelas Bash resets
IFS
for new shells, and the variable is not set in the script. How could $flag
be split in multiple words here?– Kusalananda
yesterday
|
show 1 more comment
up vote
1
down vote
The exact answer is a bit complex. It boils down to understanding that the word false
is both a command and an string (depending on context).
A longer description:
Lets start with the string A_Non_Existing_Command.
str=A_Non_Existing_Command
So, a (In general: please quote variable expansions.)
$ if $str; then echo yes; else echo no; fi
bash: A_Non_Existing_Command: command not found
no
Will print no, as the command executed fails (it doesn't exist) and the else part gets executed. Of course, there is an error message as well (more later).
However, the test command, either test
or [
(read help test
inside bash) will test if:
the length of the string between brackets is non-zero
And, so:
$ if [ "$str" ]; then echo yes; else echo no; fi
yes
Prints a yes (as the string has a non-zero amount of characters (usually bytes)). It doesn't matter that the string is also the name of a non-existing command. In this case the value of the variable is interpreted (evaluated) as an string.
And, of course, the negative test will print no:
$ if [ ! "$str" ]; then echo yes; else echo no; fi
no
Which is exactly equivalent to [ -z "$str" ]
.
Now, changing the str
content to False
and executing the same commands:
$ str=false
$ if "$str" ; then echo yes; else echo no; fi
no
$ if [ "$str" ]; then echo yes; else echo no; fi
yes
$ if [ ! "$str" ]; then echo yes; else echo no; fi
no
If you get the same with str=False
(without errors) is probably because you are in a system with a case-insensitive filesystem (where searching for False will find false without any error).
add a comment |
up vote
1
down vote
The exact answer is a bit complex. It boils down to understanding that the word false
is both a command and an string (depending on context).
A longer description:
Lets start with the string A_Non_Existing_Command.
str=A_Non_Existing_Command
So, a (In general: please quote variable expansions.)
$ if $str; then echo yes; else echo no; fi
bash: A_Non_Existing_Command: command not found
no
Will print no, as the command executed fails (it doesn't exist) and the else part gets executed. Of course, there is an error message as well (more later).
However, the test command, either test
or [
(read help test
inside bash) will test if:
the length of the string between brackets is non-zero
And, so:
$ if [ "$str" ]; then echo yes; else echo no; fi
yes
Prints a yes (as the string has a non-zero amount of characters (usually bytes)). It doesn't matter that the string is also the name of a non-existing command. In this case the value of the variable is interpreted (evaluated) as an string.
And, of course, the negative test will print no:
$ if [ ! "$str" ]; then echo yes; else echo no; fi
no
Which is exactly equivalent to [ -z "$str" ]
.
Now, changing the str
content to False
and executing the same commands:
$ str=false
$ if "$str" ; then echo yes; else echo no; fi
no
$ if [ "$str" ]; then echo yes; else echo no; fi
yes
$ if [ ! "$str" ]; then echo yes; else echo no; fi
no
If you get the same with str=False
(without errors) is probably because you are in a system with a case-insensitive filesystem (where searching for False will find false without any error).
add a comment |
up vote
1
down vote
up vote
1
down vote
The exact answer is a bit complex. It boils down to understanding that the word false
is both a command and an string (depending on context).
A longer description:
Lets start with the string A_Non_Existing_Command.
str=A_Non_Existing_Command
So, a (In general: please quote variable expansions.)
$ if $str; then echo yes; else echo no; fi
bash: A_Non_Existing_Command: command not found
no
Will print no, as the command executed fails (it doesn't exist) and the else part gets executed. Of course, there is an error message as well (more later).
However, the test command, either test
or [
(read help test
inside bash) will test if:
the length of the string between brackets is non-zero
And, so:
$ if [ "$str" ]; then echo yes; else echo no; fi
yes
Prints a yes (as the string has a non-zero amount of characters (usually bytes)). It doesn't matter that the string is also the name of a non-existing command. In this case the value of the variable is interpreted (evaluated) as an string.
And, of course, the negative test will print no:
$ if [ ! "$str" ]; then echo yes; else echo no; fi
no
Which is exactly equivalent to [ -z "$str" ]
.
Now, changing the str
content to False
and executing the same commands:
$ str=false
$ if "$str" ; then echo yes; else echo no; fi
no
$ if [ "$str" ]; then echo yes; else echo no; fi
yes
$ if [ ! "$str" ]; then echo yes; else echo no; fi
no
If you get the same with str=False
(without errors) is probably because you are in a system with a case-insensitive filesystem (where searching for False will find false without any error).
The exact answer is a bit complex. It boils down to understanding that the word false
is both a command and an string (depending on context).
A longer description:
Lets start with the string A_Non_Existing_Command.
str=A_Non_Existing_Command
So, a (In general: please quote variable expansions.)
$ if $str; then echo yes; else echo no; fi
bash: A_Non_Existing_Command: command not found
no
Will print no, as the command executed fails (it doesn't exist) and the else part gets executed. Of course, there is an error message as well (more later).
However, the test command, either test
or [
(read help test
inside bash) will test if:
the length of the string between brackets is non-zero
And, so:
$ if [ "$str" ]; then echo yes; else echo no; fi
yes
Prints a yes (as the string has a non-zero amount of characters (usually bytes)). It doesn't matter that the string is also the name of a non-existing command. In this case the value of the variable is interpreted (evaluated) as an string.
And, of course, the negative test will print no:
$ if [ ! "$str" ]; then echo yes; else echo no; fi
no
Which is exactly equivalent to [ -z "$str" ]
.
Now, changing the str
content to False
and executing the same commands:
$ str=false
$ if "$str" ; then echo yes; else echo no; fi
no
$ if [ "$str" ]; then echo yes; else echo no; fi
yes
$ if [ ! "$str" ]; then echo yes; else echo no; fi
no
If you get the same with str=False
(without errors) is probably because you are in a system with a case-insensitive filesystem (where searching for False will find false without any error).
answered 2 days ago
Isaac
9,46411443
9,46411443
add a comment |
add a comment |
Or unix.stackexchange.com/questions/99185/…
– LittleSmurfie
Jun 7 '17 at 21:51
1
This could be a good reference for you to read over. linuxacademy.com/blog/linux/…
– JayJay
Jun 7 '17 at 21:58
1
flag=False; if ! $flag ; then ...
should give you an error, unless you really have a command calledFalse
. (false
would be standard, however)– ilkkachu
Jun 7 '17 at 22:33
... for me
if [ !$flag ]; then
works (no space between!
and$flag
)– Michael D.
Jun 12 '17 at 19:48
1
I have googled that if test have 2 arguments and If the first argument is ! (exclamation mark), the expression is true if, and only if, the second argument is null. i found it here
– Krzysztof Stasiak
Jun 12 '17 at 20:11