This is part three of a series on how to approach bash programming in a way that’s safer and more structured than your basic script.
See part 1 if you want to catch the series from the start.
I’m going to assume at least a passing familiarity with bash programming, while still covering the facets of the basics on which this series will rely.
If you don’t have a familiarity with bash, you’ll be better served by starting somewhere like the following and coming back to this series once you’ve gotten your feet wet:
Getting Bash Started
If you’re on Linux, you should only need to open a terminal session to start a bash prompt.
On MacOS, you should have bash on your terminal command-line as well, however, it will be a very old version of bash. Gosh knows why Apple can’t seem to fix this.
Fortunately, there is the necessary crutch of homebrew which exists to make the Mac command-line useful. You should definitely use it to install bash, which will then be a reasonable version.
The first evergreen question of bash scripting: how to start my script?
Ok, after you open your editor to start editing the script file, that is.
Old as the classic spaces-vs-tabs debate, venerable as vi-vs-emacs, the two contenders are:
Which to use?
Well, it doesn’t really matter for the most part, unless you’re on a Mac and using homebrew (always a catch, right?).
That is to say, if your bash is not installed as
naturally you’ll want to use the
#!/usr/bin/env bash iteration of the
/usr/bin/env will force the system to search the path
bash, which will end up being whatever bash is preferred in your
path. Usually this is the right choice. It has the benefit of making
your script compatible with environments which don’t have
such as various BSD distros, or those which don’t have the latest
/bin/bash, such as MacOS.
However, if you don’t want run-time determination of which bash will be
used to invoke your script, you may prefer the shebang to be hardwired
/bin/bash (or other). That’s fine as well, as long as you know what
you’re getting. You may need to code to a particular version of bash in
that case. Yes, the bash language occasionally does change
version-to-version. This may be worth it, for example, in order to lock
a known bash for, say, an init script which will be run as root.
It’s up to you. I usually prefer to trust the user’s path and use
#!/usr/bin/env bash for portability, except in the case of init
scripts or other situations where hardwired dependencies are at a
Extension a File with the IRS
So, then, what to name the file? Well, that’s really up to you as well.
However, there is the question of the file extension, a topic almost as weathered as our last question.
I pretty much agree with the google guidelines, with one exception:
Executable scripts get no extension
Bourne-shell compatible scripts get the
Any file which uses bash-specific syntax gets the
Executable files in any non-scripting language don’t care to specify
their source langage as a file extension. There’s no reason bash scripts
need to either. Despite the fact that many developers include the
extension on any shell file, I don’t see a need for it. It’s simply
To be fair, one possibly valid reason is that you use a
syntax-highlighting editor which doesn’t detect the filetype correctly
unless the file has the
.sh extension. Consider getting a new editor.
Any executable bash script will have the shebang as the first line. Any editor worth its salt should detect such and offer the correct highlighting automatically. The file shouldn’t need an extension to detect the filetype.
I agree with the google guidelines that libraries (files only containing code for other programs) should have a file extension. This is especially true since libraries typically will not have a shebang and therefore won’t have their syntax auto-detected without an extension.
However, I part ways at using the
.sh extension exclusively. Any file
.sh extension should be Bourne shell-compatible. If you are
using bash, you should take advantage of its numerous improvements over
the Bourne shell (otherwise, stop reading this series right here). If
you do so, you therefore shouldn’t use the
.sh extension since your
script won’t be
.sh-compatible. To be clear and proper, use
Continue with part 4 - failing.