The bash tips drawings by Julia Evans caused me to test all my Bash scripts using ShellCheck.
I found good tips how to program better Bash scripts.
Except for always quote your variables:
$ shellcheck script.sh
In script.sh line xyz:
sudo $RM $dir
^-- SC2086: Double quote to prevent globbing and word splitting.
I changed this without thinking about it to
$ sudo "$RM" $dir
This is bad because RM
looked like this: RM="rm -rfd"
.
Running the script then caused this error:
sudo: rm -rfd: command not found
The programm Bash like to execute in this case is rm -rfd
. But there is no programm called rm -rfd
. The programm to execute is rm
. Not rm -rfd
. -rfd
are only programm arguments. A better way could be this:
$ RM="rm"
$ RM_OPTS="-rfd"
...
$ sudo "${RM}" ${RM_OPTS} $dir
Note that ${RM_OPTS}
has no quotes. Otherwise it would not work with RM_OPTS="-r -f -d"
and double-quoted ${RM_OPTS}
like this: sudo "${RM}" "${RM_OPTS}" $dir
. It’s the same problem. This would cause Bash to give -r -f -d
as one single argument. But rm
like to have each argument separated.
Anyway, unless you need it that complex do not do it.
I changed everything to like this:
$ sudo rm -rfd "$dir"
It always depends on the use case:
$ git add $files
While files
is a string with multiple files like file1 file2
, I do not want to double quote $files
. Each file must be a separate argument.
If you have a Git Commit Message in a variable you want double quotes:
$ msg="This is my commit message."
$ git commit -m "$msg"
Conclusion
Always quote your variables is not for general usage. It’s a good approach for some variables holding paths, but it always depends on the use case. You should not pack too much stuff into variables. Even if there are many usages and duplicate code. Keep it simple.