This is part seven 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.
Last time, we outlined a template script compatible with testing. This time we’ll look at how to source a file.
Use the Source, Luke
The primary issue with sourcing files in bash is that any relative reference to a file is dependent on the current working directory when the file is executed. It’s not based on where the script file is located.
Thus if you know the absolute pathname of the file you want sourced, you
can use that reliably. However you can’t rely on a relative pathname
./mylibrary.bash, even if it’s in the same directory as the
script containing the directive.
There are normally two options. The first is that you don’t specify a
pathname other than the filename itself, neither relative nor absolute.
Instead, you put the library somewhere on your PATH, which is searched
automatically by the source, or
., command. This means that not only
does the user have to do an installation step for the script to work
(modify PATH), but also that finding the file correctly depends on not
having another file of the same name earlier in the PATH.
The second option is discover the path of the current file and source the target file relative to that path. Here’s what that looks like:
Breaking it down, first there is
$BASH_SOURCE. This is a reference to
the first element of the BASH_SOURCE array, which is the current file,
relative to where it was called from. For example, if the file were
executed from its own directory, it might simply contain the filename
and nothing more.
Because we need the pathname to the current file, we use
--canonicalize. This is a feature of GNU readlink which returns the
precise path, including filename, of the argument. It even resolves
symlinks to the true path of the file. There is an alternative called
realpath which does the same thing, but is not as available on the
platforms on which I work.
While that returns the filename included with the path, we only want the directory name, so dirname finishes the job. After that we simply append the relative path to the file we wish to source.
The only critical thing to this approach is that you don’t change the
current working directory before you call readlink on
Note that the quotation marks are important, but we’ll get into those in a later post.
Also note that the standalone double-dashes are slightly less important, but good practice for safe bash programming.
Continue with part 8 - support library