Shell – a best practice to represent a boolean value in a shell script

shellshell-script

I know, that there are boolean values in bash, but I don't ever see them used anywhere.

I want to write a wrapper for some often looked up information on my machine, for example, is this particular USB drive inserted/mounted.

What would be the best practice to achieve that?

  • A string?

    drive_xyz_available=true
    
  • A number (0 for true, ≠0 for false)?

    drive_xyz_available=0    # evaluates to true
    
  • A function?

    drive_xyz_available() { 
        if available_magic; then 
                return 0 
        else 
                return 1 
        fi
    }
    

I mostly wonder about, what would be expected by other people who would want to use the wrapper. Would they expect a boolean value, a command like variable or a function to call?

From a security standpoint I would think the second option is the safest, but I would love to hear your experiences.

Best Answer

bool(){ return "$((!${#1}))"; }

if bool "$var"
then : do true
else : do false

Just set a variable to anything but not-null for the above to work, though [ -n "$var" ] would be shorter, if not as obvious.

In general when a script interprets an environment variable to be either true or false, it will interpret any value at all to be true (and sometimes use said value to configure some option) or else a null value as false.

The above returns the boolean !not value of its first argument's len - if the argument contains any number of characters other than 0 it returns 0, else, if no characters at all, it returns 1. This is the same test you can perform with [ -n "$var" ], basically, but it just wraps it in a little function named bool().

This is typically how a flag variable works. For example:

[ -d "$dir" ] || dir=

Where other parts of a script need only look for any value at all in $dir to gauge its usefulness. This also comes in handy where parameter substitution is concerned - as parameters can be expanded to default values to fill in for empty or unset ones, but will otherwise expand to a preset value like...

for set in yes ''
do echo "${set:-unset or null}"
done

...which would print...

yes
unset or null

Of course, it is also possible to do the opposite with :+ but that can only ever give you a preset default or nothing at all, whereas the above form can give you a value or a default value.

And so regarding the three choices - any one could work depending on how you choose to implement it. The function's return is self-testing, but, if that return needs saving for any reason, will need to be put in a variable. It depends on the use case - is the boolean value you wish to evaluate a test once and done type? If so, do the function, else either of the other two is probably necessary.

Related Question