4

I have a function called install_cont that is called twice from my bash script. However, inside that function there is a code block that I want to execute only if the boolean parameter is true. In Python I would do:

def install_cont(expres=False):
    if expres:
         # Do some code...

install_cont(True)
install_cont() # Can call with default False

How do I achieve this in bash? Reading online, I understand that all variables are string. However, what is the best way to achieve a boolean-like parameter?

2
  • bash doesn't have boolean values in the first place. It only has strings. Pick any string you like, and handle it appropriately inside the function. Commented Feb 24, 2021 at 19:01
  • make one the default case and for the other pass an optional argument and check the existence of that argument in the script. Commented Feb 24, 2021 at 19:06

5 Answers 5

8

Shell scripting doesn't have booleans, but it does have a convention for representing success as an integer. Confusingly for programmers coming from other languages, this is that 0 is success, and anything else is failure.

This is the basis of the if construct which runs a command, and tests its result for success. You can't test a variable directly with if, but you can use the test built-in, which "succeeds" if a particular test passes.

test is also spelled [ which is why you'll often see code with if [ ... ] - those brackets aren't part of the if syntax, they're just a command with a funny name. (Bash also has a [[ built-in with some extra features, but [ is more standard, so worth learning.)

The test command can perform various tests - examining numbers, checking the file system, etc. For a command-line option, you could test against the string true or false with the = binary operator.

So what you end up with is something like this:

install_cont() {
    # Name the parameter for convenience
    local expres="$1";

    if [ "$expres" = "true" ];
    then
         # Do some code...
    fi;
}

install_cont true
install_cont # default will not pass the test

If you want fancier parameters, you can have actual defaults with the slightly awkward ${foo:-default} and ${foo:=default} parameter expansion syntaxes. For example:

install_cont() {
    # Default the mode to "boring"
    local mode="${1:-boring}";

    if [ "$mode" = "exciting" ];
    then
         # Do some code...
    elif [ "$mode" = "boring" ];
    then
         # Do some code...
    else
         echo "Unrecognised mode";
    fi;
}
Sign up to request clarification or add additional context in comments.

2 Comments

Why the revert of the extraneous semicolon removal? No one should write scripts like this.
@Jens Meh, maybe a revert was unnecessary, but I'm generally more comfortable with semicolons where they aren't necessary than learning rules about when they might or might not be (waves fist at JavaScript). Consider it a reminder of where the semicolons would go if you were writing this on one line for any reason, because it's not really obvious if you're used to other languages - I get syntax errors from missing ; or putting it the wrong side of then or do all the time.
0

Like this perhaps.

your_func () {
    if [[ $1 ]]; then
        # do things if parameter was present
    fi
    # do unconditional things
}

2 Comments

So I assume that checks if parameter was present or not. That means I can pass anything? Can I call it like your_func 1 or do I need quotes?
It checks if the argument is a nonempty string. For a single token you don't need to quote it, though always quoting your strings is a good habit to get into; perhaps see also When to wrap quotes around a shell variable?
0

Bash on it's own does not have built-in boolean handling. What it does is handles strings and integers. However, you can define strings and numbers for definite exit status codes and make pseudo-boolean logic by design. Where ever you see true or false in bash, you are seeing constructs with specific exit codes. Since the default command exit codes are 0 or 1, unless you assign one to the contrary, you basically have a built-in method, if not inherently for the purpose, to perform boolean logic.

Using the test command with subsequent [] or [[]] will output a 0 for true or a 1 for false. But these are merely exit status codes.

Comments

0

Unix provides two commands:

  • true: return true value (i.e. exit value is 0)
  • false: return false value (i.e. exit value is non-0)

You can use them in if, while and until constructs.

Example:

install_cont()
{
    local expres="${1:-false}"    # Default value is false

    if "$expres"; then
        # Do some code...
    else
        # Do something else...
    fi
}

install_cont true
install_cont          # false implied

You are using Bash. If you want booleans that are also valid in arithmetic operations, then you can also use arithmetic booleans:

declare -i false=0 true=1

cond1="$true"
cond2="$false"
if ((cond1 || cond2)); then
    # Do some code...
fi

Personally, I don't use arithmetic booleans as I'm perfectly happy with true and false commands.

5 Comments

Just remember not to take arbitrary input from untrusted sources if you're going to treat them as booleans by executing them...
@ilkkachu Very true, but there are so many security traps in Bash that sanitizing input is mandatory in all cases.
You missed a great chance to include my favourite man page summaries: true - do nothing, successfully and false - do nothing, unsuccessfully
@IMSoP Sometimes, like at this very moment, I'm trying hard to do nothing but I'm not always successful :-) BTW, it's probably the first time I open the GNU manpages for true and false and I notice they even have provided the usual --help and --version options to their commands. those texts are probably much longer than the remaining source code...
@xhienne Yeah, the GNU version of true.c is sometimes used as an example of unnecessary bloat, running to a whopping 80 lines; to be fair, it also implements false via a 2-line stub false.c.
0

One of the tricky things about bash and other Bourne-derived shells is that a condition used in an if or while statement is not an expression. It's a command, and the condition is treated as true or false depending on whether the command succeeded or failed. A command indicates success by returning an exit status of 0, and failure by returning anything else.

The built-in commands true and false do nothing other than returning an exit status denoting success or failure, respectively.

The [ ... ] and [[ ... ]] constructs can be used to simulate using an expression as a condition. [ is actually a command, very nearly equivalent to the test command.

If I need the equivalent of a Boolean variable in a bash script, I use a variable whose value is either the string true or the string false. If I use that variable as a condition, it expands to the command name true or false. I just have to be careful to ensure that such a variable never takes some value other than true or false.

And it's important to remember not to use the [ ... ] syntax. With a single argument, for example

if [ false ] ; then # This is incorrect!

the command succeeds because false is a non-empty string. Remember that the [ and ] are not part of the syntax of an if statement (though they're designed to look like they are).

An example:

#!/bin/bash

func() {
    if $1 ; then
        echo In func, the condition is true
    else
        echo In func, the condition is false
    fi
}

func false
func true

The output:

In func, the condition is false
In func, the condition is true

This technique does have some drawbacks. It can break if you assign a value other than exactly true or false to a variable, or even if you misspell the name of a variable. And unlike in languages with a built-in Boolean type and false and true literals, the shell is likely to fail to diagnose such errors, causing your script to silently misbehave.

2 Comments

Just remember not to take arbitrary input from untrusted sources if you're going to treat them as booleans by executing them...
@ilkkachu Sure -- but it's also easy to accidentally set a variable's value to something other than exactly true or false, or to misspell the name of a variable. And unlike in languages with a built-in Boolean type an false and true literals, the shell isn't likely to diagnose your error. That's a substantial drawback of this technique.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.