This is the second post in the “bashing bash” series. The aim of the series is to highlight problems in bash and convince systems and software engineers to help building a better alternative.
The problem
What does the following command do?
rm -rf $mydir/
Looks like the author would like to delete $mydir
directory and everything in it. Actually it may do unexpected things because of missing quotes. The rant about quotes is in the previous post. This post is about yet another issue.
The correct commands should be:
set -u
...
rm -rf "$mydir/"
The important thing here is set -u
. Without it, when $mydir
is undefined for some reason, such as a bug in code preceding the rm
command, there is a chance to brick the machine because an undefined variable becomes an empty string so the command is silently expanded to
rm -rf /
While more experienced engineers will usually use set -eu
at the beginning of the script, omitting this declaration is a big trap for others.
Side note. You could ask why the original command has a trailing slash. The trailing slash is common and is used to signify a directory. While to the best of my knowledge the rm
should work the same without the slash, some commands are actually more correct with trailing slash. For example cp myfile mydir/
would copy the file into the directory if it exists and would cause error if it doesn’t. On the other hand, cp myfile mydir
would behave the same if directory exists but would create a mydir
file if there is no such directory nor file, which was not intended. Other commands such as rsync
also behave differently with and without the slash. So it is common to use the slash.
See also: http://www.tldp.org/LDP/abs/html/options.html – bash options
The suggested solution
In NGS, any use of an undefined variable is an exception.
ngs -e 'echo(a)'
It’s going to look prettier but even in current implementation you have all the information about what happened:
========= Uncaught exception of type 'GlobalNotFound' ========= ====== Exception of type 'GlobalNotFound' ====== === [ dump name ] === * string(len=1) a === [ dump index ] === * int 321 === [ backtrace ] === [Frame #0] /etc/ngs/bootstrap.ngs:156:1 - 156:10 [in <anonymous>] [Frame #1] /etc/ngs/bootstrap.ngs:152:17 - 152:29 [in bootstrap] [Frame #2] <command line -e switch>:1:8 - 1:9 [in <anonymous>] ...
While bash options probably have historical justification, a new language should not have such a mechanism. It complicates things a lot. In addition, the programmer should always be aware what are the current options.
Please help building a better alternative
Go to https://github.com/ilyash/ngs/ and contribute some code.