Previous | Table of Contents | Next |
In previous chapters you looked at writing short shell scripts that perform a specific task. In each shell script, you needed to perform a set of common tasks. Some examples of the required tasks are
In some cases you needed to repeat these tasks, so you used shell functions. You were able to tailor the output of these functions to suit your needs by using arguments. Many of your scripts reused functions developed for other shell scripts.
In this chapter, I will present a library of shell functions that you can use in your shell scripts to perform some common UNIX task. By using and improving on these implementations, you can avoid having to reinvent the wheel when faced with a particular problem.
In previous chapters, when you wrote shell scripts that required the use of a function, you added that function to the shell scripts file. In that model, whenever you wanted to use a function in a script, you had to copy it from a different file.
When you have two or three scripts, this is fine, but as the number of scripts you write increases, so do the number of copies of the functions. Say you locate a bug in one of your functions. Imagine how hard it would be to fix every copy of that function if the function is used in ten or more shell scripts.
To reduce the complexity involved in maintaining shell functions, it would be ideal to create a central repository of functions that you could access from your shell script. In other programming languages, a central repository of functions is called a library.
Creating a library of shell functions is exactly like creating a shell script. The main difference between the two is that a library contains only functions, whereas a script contains both functions and main code.
Main code consists of all the commands in a shell script that are not contained within a function. In the following shell script, lines 1, 2, and 4 are considered main code:
1 #!/bin/sh 2 MSG="hello" 3 echo_error() { echo "ERROR:" $@ >&2 ; } 4 echo_error $MSG
Line 3, which contains a function definition, is not considered main code.
In comparison, a library of shell functions does not contain any main code. It contains only functions. For example, the following would be considered a library:
#!/bin/sh echo_error() { echo "ERROR:" $@ >&2 ; } echo_warning() { echo "WARNING:" $@ >&2 ; }
Notice that this file contains only function definitions.
Strictly speaking, nothing is preventing a library from containing main code. The distinction between a script and a library is purely a conceptual one. To make it simpler for maintenance purposes, you should avoid having anything other than function definitions in a library script.
To use a set of functions defined in a library, you need to be able to include or require these functions in shell scripts. You can do this by using the . command. Its syntax is as follows:
. file
Here file is the name of a file that contains shell commands. If the shell functions given in the previous example were stored in a file called messages.sh, the command
. messages.sh
can be used to include the functions echo_error and echo_warning into a shell script. As an example, you can rewrite the script
1 #!/bin/sh 2 MSG="hello" 3 echo_error() { echo "ERROR:" $@ >&2 ; } 4 echo_error $MSG
to use messages.sh as follows:
1 #!/bin/sh 2 . $HOME/lib/sh/messages.sh 3 MSG="hello" 4 echo_error $MSG
Here you are assuming that the file messages.sh is stored in the directory $HOME/lib/sh. If this directory did not contain messages.sh, an error message similar to the following would be displayed:
sh: /home/ranga/lib/sh/messages.sh: No such file or directory
In most versions of the shell, the shell script exits at this point without executing any other commands. For this reason, most shell scripts include all their function libraries before executing any commands.
Unlike other languages, there are no widespread naming conventions for shell libraries or shell functions. Many programmers feel that descriptive names are best for both functions and libraries, whereas others feel that some structure such as that found in the C programming language should be used. In reality, both are good ideas.
Library Naming
For the purposes of this chapter, I assume that the shell functions that are covered are stored in the file
$HOME/lib/sh/libTYSP.sh
This naming scheme provides double redundancy and can be explained as follows:
To use this library in your scripts, you need to include it as follows:
. $HOME/lib/sh/libTYSP.sh
If you put the library in a different directory, say /usr/local/lib/sh/libTYSP.sh, your scripts need to access it as follows:
. /usr/local/lib/sh/libTYSP.sh
Function Naming
For functions, use the following naming scheme:
Previous | Table of Contents | Next |