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/arguments.sh and another file called test.sh, and make them executable using the chmod command:
mkdir -p lib
touch ./lib/arguments.sh test.sh
chmod +x ./lib/arguments.sh test.shNext, 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/arguments.sh"Next, we can open up the ./lib/arguments.sh and set it up as well:
#!/bin/bash
set -eo pipefailNamed 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" || $1 == "-h" ]]; then
usage
exit 0
elif [[ $1 == "--version" || $1 == "-v" ]]; then
version
exit 0
elif [[ $1 == "--"* ]]; then
v="${1/--/}"
export "$v"="$2"
fi
shift
done
}Note how this function also implements --help and --version. The --help will call the usage function. The --version will call the version function. More on that in the example here.
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 foundRequired 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 --tagWe could improve this a bit with writing a special usage function that explains what the script needs a input.
Final arguments.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" || $1 == "-h" ]]; then
usage
exit 0
elif [[ $1 == "--version" || $1 == "-v" ]]; then
version
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
}A more elaborate example
So, now that we have a library in place, let's create a bigger script that has a usage and version functions and some required parameters:
#!/usr/bin/env bash
set -eo pipefail
script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
source "$script_dir/lib/arguments.sh"
program_name=$0
program_version="0.0.1"
function usage {
echo ""
echo "Performs a shallow clone of a GitHub repository with a GitHub app."
echo ""
echo "usage: $program_name --repo string --branch string [--help] [--version]"
echo ""
echo " --repo string name of the service"
echo " (example: KeesCBakker/keestalkstech-code-gallery)"
echo " --branch string tag of the image to deploy"
echo " (example: main)"
echo " --version shows the version of the script."
echo " --help shows this help."
echo ""
}
function version {
echo "$program_version"
}
parse_input_args "$@"
ensure_required_input_arg "--repo" "$repo"
ensure_required_input_arg "--branch" "$branch"Enjoy!
Changelog
- Added a better example and support for
--version,-vand-h. - Initial article.