# Bash Script with a Lib for Named Parameters

**Date:** 2022-12-22  
**Author:** Kees C. Bakker  
**Categories:** bash  
**Original:** https://keestalkstech.com/bash-script-with-a-lib-for-named-parameters/

![Bash Script with a Lib for Named Parameters](https://keestalkstech.com/wp-content/uploads/2022/12/gabriel-heinzer-xbEVM6oJ1Fs-unsplash.jpg)

---

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](https://keestalkstech.com/2022/03/named-arguments-in-a-bash-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:

```sh
mkdir -p lib
touch ./lib/arguments.sh test.sh
chmod +x ./lib/arguments.sh test.sh
```

Next, open `test.sh` in your preferred text editor and set it up as follows:

```sh
#!/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:

```sh
#!/bin/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:

```sh
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](#a-more-elaborate-example).

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:

```sh
declare env="" tag="nothing"
parse_input_args "$@"

echo "Env: $env"
echo "Tag: $tag"
```

Let's test what this does:

```sho
$ ./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
```

## Required parameter validation

Often you'll need parameters not to be empty, so let's add that to our `lib.sh` as well:

```sh
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:

```sh
ensure_required_input_arg "--env" "$env"
ensure_required_input_arg "--tag" "$tag"
```

Let's test:

```sho
$ ./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](https://keestalkstech.com/2022/03/named-arguments-in-a-bash-script/#argument-validation).

## Final arguments.sh file

Our complete Bash file now looks like this:

```sh
#!/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:

```sh
#!/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

2025-01-22: Added a better example and support for `--version`, `-v` and `-h`.
2022-12-12: Initial article.
