When working on Bash scripts, it is often useful to make them more flexible by using parameters. In a previous blog post, I demonstrated how to add named parameters to a single script. However, if you want to apply this feature to multiple script files, it might make sense to move the code to a separate library file and include it in each script as needed. In this blog, I'll show you how to do this.
Initial setup
To get started, create a file called lib.sh
and another file called test.sh
, and make them executable using the chmod
command:
touch lib.sh test.sh
chmod +x lib.sh test.sh
Next, open test.sh
in your preferred text editor and set it up as follows:
#!/usr/bin/env bash
set -eo pipefail
script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
source "$script_dir/lib.sh"
Next, we can open up the test.sh
and set it up as well:
#!/usr/bin/env bash
set -eo pipefail
Named arguments function
Add the following parse_input_args
function to your lib.sh
file. This will parse all the arguments and convert them to variables:
function parse_input_args() {
while [ $# -gt 0 ]; do
if [[ $1 == "--help" ]]; then
usage
exit 0
elif [[ $1 == "--"* ]]; then
v="${1/--/}"
export "$v"="$2"
fi
shift
done
}
With this code you're able to set variables in your calling script. Let's declare two variables in our test.sh
and see how it works:
declare env="" tag="nothing"
parse_input_args "$@"
echo "Env: $env"
echo "Tag: $tag"
Let's test what this does:
$ ./test.sh
Env:
Tag: nothing
$ ./test.sh --env dev --tag hello
Env: dev
Tag: hello
$ ./test.sh --help
lib.sh: line 9: usage: command not found
The implementation supports a help parameter out of the box: it will call the usage
function. More on that here.
Required parameter validation
Often you'll need parameters not to be empty, so let's add that to our lib.sh
as well:
function function_exists() {
declare -f -F "$1" > /dev/null
return $?
}
function die {
printf "Script failed: %s\n\n" "$1"
exit 1
}
function ensure_required_input_arg(){
name=$1
value=$2
if [[ -z "$value" ]]; then
function_exists usage && usage
die "Missing parameter $name"
fi
}
Add it to the script like this:
ensure_required_input_arg "--env" "$env"
ensure_required_input_arg "--tag" "$tag"
Let's test:
$ ./test.sh --env dev
Env: dev
Tag: nothing
$ ./tests.sh --env dev --tag
Script failed: Missing parameter --tag
We could improve this a bit with writing a special usage
function that explains what the script needs a input.
Final lib.sh file
Our complete Bash file now looks like this:
#!/usr/bin/env bash
set -eo pipefail
function parse_input_args() {
while [ $# -gt 0 ]; do
if [[ $1 == "--help" ]]; then
usage
exit 0
elif [[ $1 == "--"* ]]; then
v="${1/--/}"
export "$v"="$2"
fi
shift
done
}
function function_exists() {
declare -f -F "$1" > /dev/null
return $?
}
function die {
printf "Script failed: %s\n\n" "$1"
exit 1
}
function ensure_required_input_arg(){
name=$1
value=$2
if [[ "$value" == "" ]]; then
function_exists usage && usage
die "Missing parameter $name"
fi
}
And we can "include" it like this:
script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
source "$script_dir/lib.sh"
Enjoy!