bash - What do the brackets in if-statements do? [duplicate]

The name of the pictureThe name of the pictureThe name of the pictureClash 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?).










share|improve this 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 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







  • 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














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?).










share|improve this 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 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







  • 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












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?).










share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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







  • 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






  • 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 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







  • 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










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, and help test in any bash shell.

  • Why does my shell script choke on whitespace or other special characters?





share|improve this answer






















  • +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 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

















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).






share|improve this answer



























    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, and help test in any bash shell.

    • Why does my shell script choke on whitespace or other special characters?





    share|improve this answer






















    • +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 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














    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, and help test in any bash shell.

    • Why does my shell script choke on whitespace or other special characters?





    share|improve this answer






















    • +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 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












    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, and help test in any bash shell.

    • Why does my shell script choke on whitespace or other special characters?





    share|improve this answer














    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, and help test in any bash shell.

    • Why does my shell script choke on whitespace or other special characters?






    share|improve this answer














    share|improve this answer



    share|improve this answer








    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 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
















    • +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 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















    +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












    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).






    share|improve this answer
























      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).






      share|improve this answer






















        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).






        share|improve this answer












        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).







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 2 days ago









        Isaac

        9,46411443




        9,46411443












            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            Bahrain

            Postfix configuration issue with fips on centos 7; mailgun relay