Bash arrays and `set -u`
Often you need to progressively build up a set of commandline arguments in bash
, like so:
This usually works, but is a bit rubbish:
- this will break if
$LOGFILE
has a space in it, becausebash
will split it into multiple arguments - adding a flag is kind of tedious with the
FLAGS="$FLAGS ..."
boilerplate $FLAGS
ends up with a leading space, which is entirely fine but still feels ugly
Arrays solve these issues nicely. They can store elements with spaces, and there’s a nice append syntax:
You need to remember the weird "${VAR[@]}"
syntax, but you get used to that (writing "$@"
to pass along “all of this scripts arguments” is actually shorthand for "${@[@]}"
, which may help you remember).
Problem: “there’s no such thing as an empty array”
The problem is that in bash
, an empty array is considered to be unset. I can’t imagine any reason why this should be true, but that’s bash
for you. My problem is that I always use set -u
in scripts I write, so that a command will fail if I reference a variable which doesn’t exist (just like a real programming language). But in bash
, this will fail:
Ugh.
The solution is even more weird bash
syntax:
(thanks, Stack Overflow)
Which roughly translates to “if FLAGS[@]
is set, then insert the value of FLAGS[@]
, otherwise expand to nothing”.
Note the placement of the quotes - quoting the first instance of ${FLAGS[@]}
will lead to an empty string argument (instead of no argument) if $FLAGS
is empty. And failing to quote the second instance of ${FLAGS[@]}
will mean it breaks arguments on spaces, which was the whole reason we used an array in the first place.
One more trick in your bag of weird bash tricks
Depending on your outlook, this is either another useful trick to help you write more robust bash
, or yet another example of how bash
actively discourages decent programming practices, highlighting how you really really really shouldn’t use bash
for anything nontrivial.