There are several places in your shell script where you would like to give the user a usage message (a message describing the proper syntax for the command), but you don’t want to keep repeating the code for the same echo statement.
Isn’t there a way to do this just once and have several references to it?
If you could make the usage message its own script, then you could just invoke it anywhere in your original script—but that requires two scripts, not one.
Besides, it seems odd to have the message for how to use one script be the output of a different script.
Isn’t there a better way to do this?
You need a bash function. At the beginning of your script put something like this:
1 2 3 4 |
function usage ( ) { printf "usage: %s [ -a | - b ] file1 ... filen\n" $0 > &2 } |
Then later in your script you can write code like this:
1 2 3 4 |
if [ $# -lt 1] then usage fi |
Functions may be defined in several ways ([ function ] name ( ) compound-command [redirections]).
We could write a function definition any of these ways:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
function usage ( ) { printf "usage: %s [ -a | - b ] file1 ... filen\n" $0 > &2 } function usage { printf "usage: %s [ -a | - b ] file1 ... filen\n" $0 > &2 } usage ( ) { printf "usage: %s [ -a | - b ] file1 ... filen\n" $0 > &2 } usage ( ) { printf "usage: %s [ -a | - b ] file1 ... filen\n" $0 > &2 } |
Either the reserved word function or the trailing ( ) must be present.
If function is used, the () are optional.
We like using the word function because it is very clear and readable, and it is easy to grep for; e.g., grep ‘^function’ script will list the functions in your script.
This function definition should go at the front of your shell script, or at least somewhere before you need to invoke it.
The definition is, in a sense, just another bash statement. But once it has been executed, then the function is defined.
If you invoke the function before it is defined you will get a “command not found” error.
That’s why we always put our function definitions first before any other commands in our script.
Our function does very little; it is just a printf statement.
Because we only have one usage message, if we ever add a new option, we don’t need to modify several statements, just this one.
The only argument to printf beyond the format string is $0, the name by which the shell script was invoked.
You might even want to use the expression $(basename $0) so that only the last part of any pathname is included.
Since the usage message is an error message, we redirect the output of the printf to standard error.
We could also have put that redirection on the outside of the function definition, so that all output from the function would be redirected:
1 2 3 4 5 |
function usage ( ) { printf "usage: %s [ -a | - b ] file1 ... filen\n" $0 } > &2 |