Why Are We Still Using Bash?

Article trying to explain why you may not want to use bash for larger scripting work.

1147 views
d

By. Jacob

Edited: 2019-12-10 08:10

The process of learning bash has been extremely painful for me. I have probably spent several days (and some nights) learning the exact strict syntax. But, before this, I have done various smaller .sh scripts when I needed them.

Recently I made my largest bash script to date, which is trying to fix a problem occurring on resolution change in KDE Plasma. I however had to use PHP to do a simple literal string replacement, since it was just too difficult using commands in bash alone. I will try again later, when I get the time.

Bash scripting is probably one of the hardest things I have learned so far, and there is still things I have not found out how to do yet.

Everything is easy with practice, or so they say. But, there is also the issue of other people reading your code. The question is, why are we still doing scripting in bash when we have better, easier, languages such as PHP, JavaScript or Python?

Problems using bash

Many of us are not really using bash to do complex stuff, since we will essentially just be calling system programs (commands), which might cause problems if we are not careful.

What we should be doing, is first check if each command we use in the script is installed before we use them. Some commands are build-in, so we do not need to check for those. But if we plan on using Python or PHP, then we should first check if the binaries are installed and executable.

This is simple reasonable efforts towards writing code that is more reusable and portable. Which brings me to the next issue.

Bash is not object orientated. You could probably code-around this, and introduce your own OOP functionality. But why would you? It does have functions, however:

my_function () {
  echo "hallo world"
}

# Calling my_function()
my_function

Variables are global by default, and while this makes them easy to understand, it also means that even if you declare a variable inside a function, it will be available globally.

Also, when declaring your variables, you can not have spaces before or after the equals sign (=), which has caused me a great deal of pain while learning.

And likewise, the syntax of if statements is not completely straight forward to someone coming from another language, and it will take a lot of practice. Variables are also not typed, meaning all variables are treated as strings.

The problem I have with the if syntax is that it has to be very precise. You have to use square brackets [ $something = $otherthing ], and even if just a space at the start or end is missing, your statement will break:

something="bah"
otherthing="bah"

if [$something = $otherthing ]
then
    echo "yeah"
fi

The above will result in an error like this:

./my_script.sh: 8: ./my_script.sh: [bah: not found

You have to be very precise, and include a space at both the start and the end:

something="bah"
otherthing="bah"

if [ $something = $otherthing ]
then
    echo "yeah"
fi

Quoting and escaping nightmare

In bash, there are just so many "special cases" that it can be very hard to write portable scripts.

Dealing with spaces in path names is one example, but that is just a minor problem that I had to deal with. I solved it by doing this, when calling another script:

scriptdir="/some path/name/"
echo "$(php "$script_dir"/str_replace.php "$source" "$replacement")"

Note. the use of double quotes around $script_dir.

As shown above, spaces in path names can be dealt with relatively easy by quoting the variable containing the path. Escaping spaces is not necessary afaik. But, my point is that such hackery should not be needed in the first place.

This brings me to my next point. Obtaining the path for the directory of the script is not as straight forward as I am used to in PHP. People have come up with complex multi-line functions to do this. I simply choose to do:

script_dir=$(dirname "$(readlink -f "$0")")
echo $script_dir

And this might not be the most portable way, but it works in my specific circumstances.

Expanding a stored tilde character

For some reason, a tilde character stored in a variable will not be expanded properly when used later, instead leaving you with a literal tilde character.

This is a problem when working with user-supplied file system paths, because it will result in File or Directory Not Found errors.

The pure bash solutions to this problem that I have seen have been unnecessarily complicated, some even making use of dangerous eval bash build-in. Instead, I decided just to use a Python based solution.

Conclusion

I think bash has a place when it comes to system administration, and for doing simple things. But, we have to be very careful, since there are so many "special cases" we have to deal with when writing scripts that are used by others.

I also think it is fine to use Python, PHP or even JavaScript, if you are more comfortable in those languages.

In addition to the complex syntax, there are also tiny differences between shells. Bash is not the same as dash, and sh does not always point to bash. For example, in more recent versions of Ubuntu, sh points to dash, which means your script might not work as intended unless great care is taken while writing the script.

Tell us what you think:

  1. How to read user input from shell scripts using the read command.
  2. How to use the tilde character in bash scripts, having it point to the users home directory as expected.
  3. How to make a simple bash script that watches files for changes.
  4. How to generate, and compare hashes from terminal using bash and PHP scripts in Linux.

More in: Bash Tutorials