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











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 Nov 16 at 7:09


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 Nov 16 at 7:09


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




8,73552862










asked Jun 7 '17 at 21:40









dkv

22728




22728




marked as duplicate by Sergiy Kolodyazhnyy, elbarna, Thomas, RalfFriedl, Romeo Ninov Nov 16 at 7:09


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 Nov 16 at 7:09


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
    Nov 15 at 18:25












  • @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
    Nov 15 at 19:02












  • Yes, Sir. True.
    – Christopher
    Nov 15 at 19:03










  • 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
    Nov 16 at 0:16










  • @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
    Nov 16 at 6:36


















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
      Nov 15 at 18:25












    • @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
      Nov 15 at 19:02












    • Yes, Sir. True.
      – Christopher
      Nov 15 at 19:03










    • 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
      Nov 16 at 0:16










    • @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
      Nov 16 at 6:36















    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
      Nov 15 at 18:25












    • @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
      Nov 15 at 19:02












    • Yes, Sir. True.
      – Christopher
      Nov 15 at 19:03










    • 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
      Nov 16 at 0:16










    • @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
      Nov 16 at 6:36













    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 Nov 15 at 19:05

























    answered Nov 15 at 18:04









    Kusalananda

    116k15218352




    116k15218352












    • +1 Case insensitivity by default thankfully came to an end with the introduction of APFS on macOS High Sierra.
      – Christopher
      Nov 15 at 18:25












    • @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
      Nov 15 at 19:02












    • Yes, Sir. True.
      – Christopher
      Nov 15 at 19:03










    • 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
      Nov 16 at 0:16










    • @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
      Nov 16 at 6:36


















    • +1 Case insensitivity by default thankfully came to an end with the introduction of APFS on macOS High Sierra.
      – Christopher
      Nov 15 at 18:25












    • @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
      Nov 15 at 19:02












    • Yes, Sir. True.
      – Christopher
      Nov 15 at 19:03










    • 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
      Nov 16 at 0:16










    • @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
      Nov 16 at 6:36
















    +1 Case insensitivity by default thankfully came to an end with the introduction of APFS on macOS High Sierra.
    – Christopher
    Nov 15 at 18:25






    +1 Case insensitivity by default thankfully came to an end with the introduction of APFS on macOS High Sierra.
    – Christopher
    Nov 15 at 18:25














    @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
    Nov 15 at 19:02






    @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
    Nov 15 at 19:02














    Yes, Sir. True.
    – Christopher
    Nov 15 at 19:03




    Yes, Sir. True.
    – Christopher
    Nov 15 at 19:03












    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
    Nov 16 at 0:16




    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
    Nov 16 at 0:16












    @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
    Nov 16 at 6:36




    @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
    Nov 16 at 6:36












    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 Nov 15 at 23:36









        Isaac

        9,63411443




        9,63411443















            Popular posts from this blog

            Morgemoulin

            Scott Moir

            Souastre