How can I declare and use Boolean variables in a shell script?

1,335,774

Solution 1

Revised Answer (Feb 12, 2014)

the_world_is_flat=true
# ...do something interesting...
if [ "$the_world_is_flat" = true ] ; then
    echo 'Be careful not to fall off!'
fi

Original Answer

Caveats: https://stackoverflow.com/a/21210966/89391

the_world_is_flat=true
# ...do something interesting...
if $the_world_is_flat ; then
    echo 'Be careful not to fall off!'
fi

From: Using boolean variables in Bash

The reason the original answer is included here is because the comments before the revision on Feb 12, 2014 pertain only to the original answer, and many of the comments are wrong when associated with the revised answer. For example, Dennis Williamson's comment about bash builtin true on Jun 2, 2010 only applies to the original answer, not the revised.

Solution 2

TL;DR

my_bool=true

if [ "$my_bool" = true ]

Issues with Miku's (original) answer

I do not recommend the accepted answer1. Its syntax is pretty, but it has some flaws.

Say we have the following condition.

if $var; then
  echo 'Muahahaha!'
fi

In the following cases2, this condition will evaluate to true and execute the nested command.

# Variable var not defined beforehand. Case 1
var=''  # Equivalent to var="".      # Case 2
var=                                 # Case 3
unset var                            # Case 4
var='<some valid command>'           # Case 5

Typically you only want your condition to evaluate to true when your "Boolean" variable, var in this example, is explicitly set to true. All the other cases are dangerously misleading!

The last case (#5) is especially naughty because it will execute the command contained in the variable (which is why the condition evaluates to true for valid commands3, 4).

Here is a harmless example:

var='echo this text will be displayed when the condition is evaluated'
if $var; then
  echo 'Muahahaha!'
fi

# Outputs:
# this text will be displayed when the condition is evaluated
# Muahahaha!

Quoting your variables is safer, e.g. if "$var"; then. In the above cases, you should get a warning that the command is not found. But we can still do better (see my recommendations at the bottom).

Also see Mike Holt's explanation of Miku's original answer.

Issues with Hbar's answer

This approach also has unexpected behavior.

var=false
if [ $var ]; then
  echo "This won't print, var is false!"
fi

# Outputs:
# This won't print, var is false!

You would expect the above condition to evaluate to false, thus never executing the nested statement. Surprise!

Quoting the value ("false"), quoting the variable ("$var"), or using test or [[ instead of [, do not make a difference.

What I do recommend:

Here are ways I recommend you check your "Booleans". They work as expected.

my_bool=true

if [ "$my_bool" = true ]; then
if [ "$my_bool" = "true" ]; then

if [[ "$my_bool" = true ]]; then
if [[ "$my_bool" = "true" ]]; then
if [[ "$my_bool" == true ]]; then
if [[ "$my_bool" == "true" ]]; then

if test "$my_bool" = true; then
if test "$my_bool" = "true"; then

They're all pretty much equivalent. You'll have to type a few more keystrokes than the approaches in the other answers5, but your code will be more defensive.


Footnotes

  1. Miku's answer has since been edited and no longer contains (known) flaws.
  2. Not an exhaustive list.
  3. A valid command in this context means a command that exists. It doesn't matter if the command is used correctly or incorrectly. E.g. man woman would still be considered a valid command, even if no such man page exists.
  4. For invalid (non-existent) commands, Bash will simply complain that the command wasn't found.
  5. If you care about length, the first recommendation is the shortest.

Solution 3

There seems to be some misunderstanding here about the Bash builtin true, and more specifically, about how Bash expands and interprets expressions inside brackets.

The code in miku's answer has absolutely nothing to do with the Bash builtin true, nor /bin/true, nor any other flavor of the true command. In this case, true is nothing more than a simple character string, and no call to the true command/builtin is ever made, neither by the variable assignment, nor by the evaluation of the conditional expression.

The following code is functionally identical to the code in the miku's answer:

the_world_is_flat=yeah
if [ "$the_world_is_flat" = yeah ]; then
    echo 'Be careful not to fall off!'
fi

The only difference here is that the four characters being compared are 'y', 'e', 'a', and 'h' instead of 't', 'r', 'u', and 'e'. That's it. There's no attempt made to call a command or builtin named yeah, nor is there (in miku's example) any sort of special handling going on when Bash parses the token true. It's just a string, and a completely arbitrary one at that.

Update (2014-02-19): After following the link in miku's answer, now I see where some of the confusion is coming from. Miku's answer uses single brackets, but the code snippet he links to does not use brackets. It's just:

the_world_is_flat=true
if $the_world_is_flat; then
  echo 'Be careful not to fall off!'
fi

Both code snippets will behave the same way, but the brackets completely change what's going on under the hood.

Here's what Bash is doing in each case:

No brackets:

  1. Expand the variable $the_world_is_flat to the string "true".
  2. Attempt to parse the string "true" as a command.
  3. Find and run the true command (either a builtin or /bin/true, depending on the Bash version).
  4. Compare the exit code of the true command (which is always 0) with 0. Recall that in most shells, an exit code of 0 indicates success and anything else indicates failure.
  5. Since the exit code was 0 (success), execute the if statement's then clause

Brackets:

  1. Expand the variable $the_world_is_flat to the string "true".
  2. Parse the now-fully-expanded conditional expression, which is of the form string1 = string2. The = operator is bash's string comparison operator. So...
  3. Do a string comparison on "true" and "true".
  4. Yep, the two strings were the same, so the value of the conditional is true.
  5. Execute the if statement's then clause.

The no-brackets code works, because the true command returns an exit code of 0, which indicates success. The bracketed code works, because the value of $the_world_is_flat is identical to the string literal true on the right side of the =.

Just to drive the point home, consider the following two snippets of code:

This code (if run with root privileges) will reboot your computer:

var=reboot
if $var; then
  echo 'Muahahaha! You are going down!'
fi

This code just prints "Nice try." The reboot command is not called.

var=reboot
if [ $var ]; then
  echo 'Nice try.'
fi

Update (2014-04-14) To answer the question in the comments regarding the difference between = and ==: AFAIK, there is no difference. The == operator is a Bash-specific synonym for =, and as far as I've seen, they work exactly the same in all contexts.

Note, however, that I'm specifically talking about the = and == string comparison operators used in either [ ] or [[ ]] tests. I'm not suggesting that = and == are interchangeable everywhere in bash.

For example, you obviously can't do variable assignment with ==, such as var=="foo" (well technically you can do this, but the value of var will be "=foo", because Bash isn't seeing an == operator here, it's seeing an = (assignment) operator, followed by the literal value ="foo", which just becomes "=foo").

Also, although = and == are interchangeable, you should keep in mind that how those tests work does depend on whether you're using it inside [ ] or [[ ]], and also on whether or not the operands are quoted. You can read more about that in Advanced Bash Scripting Guide: 7.3 Other Comparison Operators (scroll down to the discussion of = and ==).

Solution 4

Use arithmetic expressions.

#!/bin/bash

false=0
true=1

((false)) && echo false
((true)) && echo true
((!false)) && echo not false
((!true)) && echo not true

Output:

true
not false

Solution 5

Long story short:

There are no Booleans in Bash

The true and false commands

Bash does have Boolean expressions in terms of comparison and conditions. That said, what you can declare and compare in Bash are strings and numbers. That's it.

Wherever you see true or false in Bash, it's either a string or a command/builtin which is only used for its exit code.

This syntax...

if true; then ...

is essentially...

if COMMAND; then ...

where the command is true. The condition is true whenever the command returns exit code 0. true and false are Bash builtins and sometimes also standalone programs that do nothing but returning the corresponding exit code.


Conditions in if..then..fi

When using square brackets or the test command, you rely on the exit code of that construct. Keep in mind that [ ] and [[ ]] are also just commands/builtins like any other. So ...

if [[ 1 == 1 ]]; then echo yes; fi

corresponds to

if COMMAND; then echo yes; fi

and the COMMAND here is [[ with the parameters 1 == 1 ]]

The if..then..fi construct is just syntactic sugar. You can always just run the commands separated by a double ampersand for the same effect:

[[ 1 == 1 ]] && echo yes

When using true and false in these testing constructs you are actually only passing the string "true" or "false" to the testing command. Here is an example:

Believe it or not but those conditions are all yielding the same result:

if [[ false ]]; then ...
if [[ "false" ]]; then ...
if [[ true ]]; then ...
if [[ "true" ]]; then ...

TL;DR; always compare against strings or numbers

To make this clear to future readers, I would recommend always using quotes around true and false:

DO

if [[ "${var}" == "true" ]]; then ...
if [[ "${var}" == "false" ]]; then ...
if [[ "${var}" == "yes" ]]; then ...
if [[ "${var}" == "USE_FEATURE_X" ]]; then ...
if [[ -n "${var:-}" ]]; then echo "var is not empty" ...

DON'T

# Always use double square brackets in bash!
if [ ... ]; then ...
# This is not as clear or searchable as -n
if [[ "${var}" ]]; then ...
# Creates impression of Booleans
if [[ "${var}" != true ]]; then ...
# `-eq` is for numbers and doesn't read as easy as `==`
if [[ "${var}" -eq "true" ]]; then ...

Maybe

# Creates impression of Booleans.
# It can be used for strict checking of dangerous operations.
# This condition is false for anything but the literal string "true".
if [[ "${var}" != "true" ]]; then ... 
Share:
1,335,774
hassaanm
Author by

hassaanm

Updated on July 16, 2022

Comments

  • hassaanm
    hassaanm almost 2 years

    I tried to declare a Boolean variable in a shell script using the following syntax:

    variable=$false
    
    variable=$true
    

    Is this correct? Also, if I wanted to update that variable would I use the same syntax? Finally, is the following syntax for using Boolean variables as expressions correct?

    if [ $variable ]
    
    if [ !$variable ]
    
  • SourceSeeker
    SourceSeeker almost 14 years
    To explain what is happening: the if statement is executing the contents of the variable which is the Bash builtin true. Any command could be set as the value of the variable and its exit value would be evaluated.
  • michael
    michael almost 12 years
    @pms The operators "-o" and "-a" are only for the "test" command (aka "[]"). Instead, this is "if + command", without the "test". (Like "if grep foo file; then ...".) So, use the normal && and || operators: # t1=true; t2=true; f1=false; # if $t1 || $f1; then echo is_true ; else echo is_false; fi; (returns "true", since t1=true) # if $t1 && $f1 || $t2; then echo is_true ; else echo is_false; fi (returns "true", since t2=true) . Again, this ONLY works because "true"/"false" are bash-builtins (returning true/false). You can't use "if $var..." unless var is a cmd (ie, true or false)
  • dolmen
    dolmen almost 11 years
    [ is not just an alias inside bash. This alias also exists as a binary file (or as a link pointing to) and can be used with the bare sh. Check ls -l /usr/bin/\[. With bash/zsh you should instead use [[ that is a true pure internal and is much more powerful.
  • Dennis
    Dennis over 10 years
    -1, see my answer for an explanation.
  • ajk
    ajk about 10 years
    Lots of incorrect information, here. /bin/true isn't being used effectively. See Dennis' answer.
  • ajk
    ajk about 10 years
    The no-bracket approach also has the advantage of letting you write clean, clear (imo) one-liners like $the_world_is_flat && echo "you are in flatland!"
  • Mike Holt
    Mike Holt about 10 years
    True. Although, I'm not advocating for (or against) either approach. I just wanted to clear up some of the misinformation that's getting voted up here, so that people who stumble upon this topic later on won't walk away with a bunch of misconceptions about how this all works.
  • chepner
    chepner about 10 years
    Using == with [ or test is not portable. Considering portability is the only advantage [/test has over [[, stick with =.
  • chepner
    chepner about 10 years
    Using == with [/test is not portable; if you want to use ==, use [[. If you want to use [, use =.
  • Mike Holt
    Mike Holt about 10 years
    @chepner You're right. I hate == and never use it in my own scripts. Not sure why I had that in there. Maybe just too much C on the brain.
  • Dennis
    Dennis over 9 years
    @Scott I use fish as my primary shell, which has a sane scripting language compared to bash in my opinion.
  • Dennis
    Dennis over 9 years
    @Kranach that's expected output and what I consider a valid command even though the man command is used incorrectly. If it were invalid, you would see man: command not found. That's what I mean with footnote #3. (Edit: Posted this before I saw your edit :))
  • Kranach
    Kranach over 9 years
    Yeah, I just couldn't find in comments any appreciation for this hidden joke, so had to point it out =)
  • Quolonel Questions
    Quolonel Questions about 9 years
    This code is not the same and does not work in the same way as the linked article. The linked code calls a program by the name stored in a variable but the code in this answer is just string comparison.
  • Trevor Boyd Smith
    Trevor Boyd Smith almost 9 years
    pros: (1.) behaviour is similar to C's way of handling bools, (2.) syntax is very concise/minimal (does not require a right-hand variable and operators like '=' or '=='), (3.) <subjective>for me I understand what happens without a long winded explanation ... contrast to Miku and Dennis' answers which both seem to require long winded explanations</subjective>
  • Quolonel Questions
    Quolonel Questions almost 9 years
    @TrevorBoydSmith Why didn't you just say, "pros: everything, cons: nothing". Would save depreciation costs on your keyboard and monitor in the long run.
  • wisbucky
    wisbucky almost 9 years
    @ajk The reason that a lot of the comments seem incorrect is because miku's original answer was revised by another user on Feb 12, 2014, so it invalidated most of the previous comments.
  • wisbucky
    wisbucky almost 9 years
    The reason for the confusion is that miku's original answer stood for 4 years. All the references to the builtin true were made regarding the original answer. (The revised answer on Feb 12, 2014 was not submitted by miku.) I have edited the answer to include both original and revised. Then people's comments make sense.
  • Mike Holt
    Mike Holt almost 9 years
    @wisbucky Thanks for that. I hadn't realized that there was a prior version of miku's answer, although I did note in my update on 2/19/2014 that the article linked to in miku's answer was doing something different.
  • wisbucky
    wisbucky almost 9 years
    For me, conceptually it is easier to understand if I use bool="true". Then it's clear that it's just a string and not some special value or builtin.
  • Seldom 'Where's Monica' Needy
    Seldom 'Where's Monica' Needy almost 9 years
    From reading the answers offered here, I get the impression that there's no such thing as actually using the real true. Is there a way? I suspect many programmers who are used to stricter languages viewing this answer to assist them in mixing up some bash glue to make their lives a bit easier would want an === operator so that strings and "booleans" aren't actually interchangeable. Should they just stick to 0 and 1 and use (( $maybeIAmTrue )) as suggested in Quolonel Question's answer?
  • Peter Cordes
    Peter Cordes over 8 years
    For interactive use, like one-liners, make sure to leave a space after !, or it will do history expansion. ((! foo)) works, so does ! ((foo)). I love this solution, BTW. Finally a concise way to do boolean variables. ((foo || bar)) works as expected.
  • Peter Cordes
    Peter Cordes over 8 years
    (()) expands variables recursively, which I wasn't expecting. foo=bar; bar=baz; ((foo)) && echo echo prints nothing, but it's true with baz=1. So you can support foo=true and foo=false as well as 0 or 1 by doing true=1.
  • jarno
    jarno about 8 years
    @dolmen [ and test is also a Bash SHELL BUILTIN COMMAND according to Bash manual page, so there should not be an issue in performance. Same thing with e.g. Dash. (/bin/sh may just a symlink to /bin/dash). To use the executable you have to use full path i.e. /usr/bin/\[.
  • dolmen
    dolmen about 8 years
    If var is a local variable where assignments are completely controlled in your program, there is no risk in using @miku's answer without quotes.
  • dolmen
    dolmen about 8 years
    The original answer was just better and completely safe as long as the assignments of the variable are completely controlled inside your script.
  • dolmen
    dolmen about 8 years
    Where you remove the parentheses, this is exactly @miku's original answer at the top.
  • Dennis
    Dennis about 8 years
    @dolmen absolutely, evaluating input isn't as risky when you control the input, but I still consider it a bad practice that should be avoided if it can easily be avoided. Someone who has only ever seen and used the former style may not know about its flaws which can cause unexpected behaviour.
  • will
    will about 8 years
    Without parentheses the expression doesn't evaluate.
  • Benjamin W.
    Benjamin W. about 8 years
    Why don't you just do declare -ir false=0 true=1? What's the advantage of using an array?
  • sjsam
    sjsam about 8 years
    @BenjaminW. I just wanted to mention about the r option & readonly command. I would do it the way you suggested in my scripts
  • phk
    phk over 7 years
    The true/false built-ins aren't used here (ignore what the syntax highlighting of some editors might imply), especially in the […] cases you can think of it as a simple string here (one that is given as a parameter to the [ command).
  • Loenix
    Loenix over 7 years
    VAR=true; $VAR && echo "TRUE" || echo "FALSE"; Show True and VAR=false; $VAR && echo "TRUE" || echo "FALSE"; Show False. So this is working properly...
  • phil294
    phil294 almost 7 years
    wouldnt it make more sense to use 0 and 1 instead of false and true then? aka if [[ $a == 0 ]]; then ..
  • phil294
    phil294 almost 7 years
    why not integers?
  • Mike Holt
    Mike Holt almost 7 years
    To address SeldomNeedy's comment, yes, you can use the real true, but generally not as something to compare a variable against, since the real true has no value per se. All it does is set the exit status to 0, indicating success. It's worth noting that it's essentially equivalent to the so-called "null command", or :. As far as using 0 and 1, that's what I do in all my scripts these days where I need booleans. And I use the (( )) operator instead of [[ ]] to evaluate. So, for example, if I have flag=0, I can then do if (( flag )); then ...
  • andras.tim
    andras.tim over 6 years
    I think this answer can kill the kitties because the true in the_world_is_flat assignment is a command in the original answer! Let's check with the_world_is_flat=date...
  • Hubert Grzeskowiak
    Hubert Grzeskowiak over 6 years
    DO NOT USE THE ORIGINAL ANSWER! It is executing a command every time you check the value and it's easy to forget how it works and put square brackets around it (which breaks it all). Short answer is: bash does not have booleans. It only has builtin testing ([ ], [[ ]], test) which evaluates to a boolean'ish exit code. You cannot define that boolean, though.
  • Hubert Grzeskowiak
    Hubert Grzeskowiak over 6 years
    About the newer answer: it is simple string comparison. When in bash, you should rather use double square brackets and quote everything so people know it's strings and nothing special.
  • Hubert Grzeskowiak
    Hubert Grzeskowiak over 6 years
    Big downside of this: The double braces have exit code 1 if the result of the expression is 0, so if you are using strict error checking (set -e), which you totally should, this will lead to unforeseen errors.
  • Hubert Grzeskowiak
    Hubert Grzeskowiak over 6 years
    Also you can't use test flags (see man test) with this. It is for arithmetical expressions only
  • Hubert Grzeskowiak
    Hubert Grzeskowiak over 6 years
    @Blauhirn because integers are used differently depending on languages. In some languages 0 coerces to false and 1 to true. In regards to program exit codes (which bash historically uses) it's 0 for positive outcome or true and everything else is negative/error or false.
  • Hubert Grzeskowiak
    Hubert Grzeskowiak over 6 years
    You should declare your constants readonly. Also please always use curly brackets when using variables. It's a convention everyone should stick to IMHO. Big downside of this solution is that you cannot mix the algebraic expression with test flags or string comparisons.
  • Quolonel Questions
    Quolonel Questions over 6 years
    @HubertGrzeskowiak Since you have demonstrated very limited understanding I suggest you read why set -e is a bad idea.
  • Hubert Grzeskowiak
    Hubert Grzeskowiak over 6 years
    @quolonel thank you for the very helpful resource. Of course my understanding is limited - it is human nature to be limited in all understanding no matter the domain. However, would you mind telling me which of my statements lead you to the assumption that my understanding of this particular matter is incomplete?
  • Hubert Grzeskowiak
    Hubert Grzeskowiak over 6 years
    I think I am well aware of the implications of '-e' and I would still recommend it for multiple reasons
  • Hubert Grzeskowiak
    Hubert Grzeskowiak over 6 years
    In case you are referring to the exception of certain chained commands from the special error-intolerant mode, I think relying on the next editor to know these implications is too risky and not worth the seemingly better syntax. I've seen arithmetic expressions on their own line a few times too much, I guess
  • phil294
    phil294 over 6 years
    @will yes it does. You dont need the ()s.
  • will
    will over 6 years
    @Blauhirn ... Hi, I based my comments on experiments with GNU Bash on a Linux Mint /Ubuntu PC. You are probably right in theory ()-s are not needed. My only response, is try it out, it seems to depend on Bash version, the actual expression or context and such.
  • Levi
    Levi over 6 years
    @HubertGrzeskowiak "It is executing a command every time you check the value": this is only true for very old shells. true (and false) are built-in commands in bash (and virtually every other shell): no new process is started.
  • qodeninja
    qodeninja over 6 years
    maybe I missed something but why dont true and false declared in this way use the dollar sign? $true $false
  • Timothy Swan
    Timothy Swan over 6 years
    [[ -e file.txt ]] ; echo "$?" Prints 0 if file is there. This is necessary to include as part of the answer because otherwise people won't know how to store the boolean.
  • phk
    phk about 6 years
    I prefer to use T and F to make clear that those aren't real boolean values.
  • Quolonel Questions
    Quolonel Questions about 5 years
    Literally just copying my answer and making it worse.
  • sjsam
    sjsam about 5 years
    @QuolonelQuestions Bash variables are not typed, hence there is no point in saying declare and use boolean variables.We could just, in more than one way, mimic/assume that a variable has a type. I didn't see that mentioned anywhere in your answer.
  • San
    San almost 5 years
    Answers like these and Contributors like you make Stack Overflow the best place for devs. Thank you!
  • alfiogang
    alfiogang almost 5 years
    I write this script for print greating on the first time (usefull in huge directory for command to signal progress). limit=10 first=1 for ((i=1;i<=$limit;i++)); do ((first)) && echo "Hello" && first=0 echo $i done
  • WinEunuuchs2Unix
    WinEunuuchs2Unix almost 5 years
    ((Debug)) && echo stuff is so much simpler than the longer version[[ "$fDebug" == true ]] && echo stuff. You've got my vote.
  • mgutt
    mgutt over 4 years
    Does not work for me. It returns true and not true?! ash-4.3# false=0 ash-4.3# true=1 ash-4.3# ((false)) && echo false ash-4.3# ((true)) && echo true true ash-4.3# ((!false)) && echo not false ((false=0)) && echo not false ash-4.3# ((!true)) && echo not true ((true=1)) && echo not true not true
  • mgutt
    mgutt over 4 years
    sh --help returns GNU bash, version 4.3.48(1)-release-(x86_64-pc-linux-gnu) so its simply bash (this is the shell of a Synology NAS). And the question was related a "shell" and not specific shell variant. So in which shell does your code work?
  • wjandrea
    wjandrea over 4 years
    There is one problem with this: invalid values cause syntax errors, e.g. s=/home; ((s)) outputs bash: ((: /home: syntax error: operand expected (error token is "/home")
  • Quolonel Questions
    Quolonel Questions over 4 years
    @wjandrea That's the opposite of a problem because now you have a mechanism to identify bugs in your code.
  • matanster
    matanster over 4 years
    Worth noting that equality evaluates to 1 and so these conditions actually check the opposite of what they would in most other programming languages?
  • jarno
    jarno over 4 years
    This is not a variable that you could test, but a constant function
  • johnraff
    johnraff over 4 years
    @jarno Is testing the return value of a function different from testing a variable, for the purposes of a script?
  • jarno
    jarno over 4 years
    Well, the question is about variables.
  • johnraff
    johnraff over 4 years
    True, although the usage in a shell script would be the same.
  • Peter Mortensen
    Peter Mortensen over 4 years
    You have it now.
  • Peter Mortensen
    Peter Mortensen over 4 years
    Yes, functional decomposition is under-appreciated.
  • tahiche
    tahiche about 4 years
    Note the importance of the space... "if [ "$the_world_is_flat"=true ]" (no space around = operator) will always be true. This gets me every time
  • Jonathan Cross
    Jonathan Cross almost 4 years
    @qodeninja In bash you never use the $ when declaring -- only when evaluating.
  • Jonathan Cross
    Jonathan Cross almost 4 years
    GFlags makes no sense in this answer -- it is a C++ library. It cannot be directly used in shell scripts.
  • gogasca
    gogasca almost 4 years
    Updated response to shFlags which is a port of GFlags to shell.
  • Weijun Zhou
    Weijun Zhou almost 4 years
    I can't agree with "always use double brackets in bash". In fact in almost all the scripts I've written I am using single brackets, except when I need to do pattern matching. I think one should understand the difference between [(i.e. test) and [[ and use the one that is suitable for his need.
  • Hubert Grzeskowiak
    Hubert Grzeskowiak almost 4 years
    @WeijunZhou mind elaborating in which cases single brackets are better?
  • Weijun Zhou
    Weijun Zhou almost 4 years
    It's more of a personal taste, I just find that it is too bold to say "Always use double square brackets in bash". But there are some edge cases that I have used. Single brackets allow you to specify the test itself in a var. As an oversimplified example, consider if ....; then mytest='-gt'; else mytest='-eq'; fi; #several lines of code; if [ "$var1" "$mytest" "$var2" ]; then ...; fi
  • Hubert Grzeskowiak
    Hubert Grzeskowiak almost 4 years
    @WeijunZhou Your example is a strong argument against single square brackets. It makes the code much harder to understand and opens the window wide open to errors. Double brackets are more strict and encourage cleaner code.
  • Hubert Grzeskowiak
    Hubert Grzeskowiak almost 4 years
    @WeijunZhou your code can be vey easily refactored to not require a dynamic comparison.
  • Weijun Zhou
    Weijun Zhou almost 4 years
    Actually I wanted to quote stackoverflow.com/a/47576482/3966456 at my first reply. The main point being "There are POSIX equivalents for every [[ ]] construct I've seen." As there is another whole question for this matter, and as you see people clearly have different opinions on this, Plus I never really have to worry whether my use of single brackets has errors now that I have shellcheck. I think it's better to just stop here, or move the discussion to the cited question. I did not add my example as an answer/comment to that question precisely because I know it would be controversial.
  • Weijun Zhou
    Weijun Zhou almost 4 years
    I think I will rewrite my comment posted before the last one (and that one will be deleted) to clarify my point. Admittedly the example I gave is an edge case, not something that you would do excessively in production code. My point is, I don't like the restriction [[ puts on me by auto-quoting variables and escaping parenthesis because that closes a lot of possibilities. Additionally, such auto-escaping is inconsistent with other parts of bash. If I have an unquoted variable in [[, I want it to bite me the first time I write it, not later when I change the if to something else.
  • Jemar Jones
    Jemar Jones over 3 years
    Super casual flat earther comment, nothing to see here
  • zaTricky
    zaTricky about 3 years
    Doesn't the single = inside the [] need to be doubled == ?
  • Bill Gale
    Bill Gale about 3 years
    This answer is the closest to the OP where they were interested in if ! variable and the arithmetic expressions support that. All the string approaches suffer from having to do string companions to "false" or using else constructs, if you interest is in false only, an else construct would be an awkward way to achieve that.
  • Bill Gale
    Bill Gale about 3 years
    @Dennis Since the OP also wanted to check for false, it would be helpful for this highly rated answer to present recommended ways to test for false, rather than just use an example with false to blow up another answer here.
  • Gauthier
    Gauthier almost 3 years
    Not assigning the_world_is_flat first still works as expected. Why? I'd expect the condition evaluation to result in a syntax error.
  • alper
    alper over 2 years
    would it be same if I apply it for false?
  • Teocci
    Teocci over 2 years
    I usually use this way: a=true and I evaluate like this if [ "$a" = 'true' ]; then. In our recommendation you used if [ "$my_bool" = true ]; then and if [ "$my_bool" = "true" ]; then It is my way wrong? why you didn't use simple quotes 'true' but double quotes "true"?
  • Tom Shaw
    Tom Shaw almost 2 years
    There's a serious exception - the_world_is_flat = true surely would cause the exception stupidity=true to also be false.