TL;DR: bargs - A featherweight Bash package, which enables an easy way to use command line arguments in your Bash scripts
Every time I need to write a Bash script which accepts command line arguments, I go back to this great answer in StackOverflow - How do I parse command line arguments in Bash
Let's do a quick overview of the process!
The usual way
So here I am, maintaining the command line arguments, which in turn, will be variables, in four different places. Why four? Here we go!
1 - usage function
The usage
function should pop up whenever the user attempts to provide wrong or missing arguments
usage()
{
cat << EOF
usage: bash ./scripts/packndeploy -n service_name
-n | --service_name (Required) Service to deploy
-b | --branch (master) Source branch
-h | --help Brings up this menu
EOF
}
2 - Declaring Variables
To get the command line arguments, we need to declare variables that can store them, and also set the default values for these variables/arguments.
service_name=
branch=master # default value
3 - Arguments to Variables
Mapping arguments to variables with while case shift
is a great trick to fetch variables! To learn more about it read this great tutorial or this great comment in StackOverflow
while [ "$1" != "" ]; do
case $1 in
-n | --service_name )
shift
service_name=$1
;;
-b | --branch )
shift
branch=$1
-h | --help ) usage
exit
;;
* ) usage
exit 1
esac
shift
done
4 - Verifying required arguments
After the while
loop above :point_up: we need to make sure that the required variables were provided. So here's a quick and dirty way to do it
if [ -z $service_name ]; then
echo "Service name is required, provide it with the flag: -n service_name"
exit
fi
NOTE: I'm sure that it's better to write a function that performs some of the tasks above dynamically, but it still means we need to write it or copy-paste it to our Bash script.
Motivation
I'm writing a lot of Bash scripts, and most of them require command line arguments, so I thought it'd be best to write a "wrapper script" that performs all the above-mentioned steps.
The "wrapper script" should meet the following requirements
- Manage all arguments, including the variables that they become in one place
- A beautiful usage or help message that is based on the definitions of the arguments. We'll get to that, I call it
bargs_vars
- Adding the "wrapper script" by performing minimum steps and without polluting my Bash script
The Solution - bargs
Ladies and gentlemen, I present to you bargs - a comfortable way to deal with command line arguments in Bash.
So how do you use it? Keep on reading or jump to the bargs GitHub repository to get started!
Requirements
- Bash v4.4+
- Linux Utils - We're printing beautiful stuff with the column command, that is included in Linux Utils
macOS
$ brew install util-linux
Linux (Debian/Ubuntu)
$ sudo apt-get -y update && sudo apt-get install -y bsdmainutils
Windows
Not supported (yet)
Getting Started
-
Download the script (4 kilobytes) and put it in the same folder as your code
curl -s -L bargs.link/bargs.sh --output bargs.sh
-
Creating bargs_vars - do one of the following
- Create the file
bargs_vars
, put it in the same folder asbargs.sh
- Download the existing
bargs_vars
templatecurl -s -L bargs.link/bargs_vars --output bargs_vars
- Create the file
-
Declaring arguments/variables
- The delimiter
---
is required once at the beginning, and twice in the end - If the default is empty or not defined, the argument is required
- You can't add comments to this file, use the description
- Arguments values (including default) must not contain whitespace
- Use the bargs description to set the
--help
message
--- name=person_name short=n description=What is your name? default=Willy --- name=age short=a --- name=gender short=g --- name=location short=l description=insert your location default=chocolate-factory --- name=bargs description=bash example.sh -n Willy --gender male -a 99 --- ---
- The delimiter
-
Add the following line at the beginning of your application
source bargs.sh "$@"
-
That's it! You can now reference to arguments that were declared in
bargs_vars
Usage
Using the bargs_args
above in our application - example.sh
#!/bin/bash
source bargs.sh "$@"
echo -e \
"Name:~$person_name\n"\
"Age:~$age\n"\
"Gender:~$gender\n"\
"Location:~$location" | column -t -s "~"
Usage output
-
Using the help flag
bash example.sh -h Usage: bash example.sh -n Willy --gender male -a 99 --person_name | -n [Willy] What is your name? --age | -a [Required] --gender | -g [Required] --location | -l [chocolate-factory] insert your location
-
Using default values
$ bash example.sh -a 99 --gender male Name: Willy Age: 99 Gender: male Location: chocolate-factory
-
Providing all arguments
$ bash example.sh -a 23 --gender male -l neverland -n meir Name: meir Age: 23 Gender: male Location: neverland
-
Providing an empty required argument
$ bash example.sh -a 99 --gender [ERROR] Empty argument: gender Usage: bash example.sh -n Willy --gender male -a 99 --person_name | -n [Willy] What is your name? --age | -a [Required] --gender | -g [Required] --location | -l [chocolate-factory] insert your location
-
Providing an unknown argument
$ bash example.sh -a 99 -u meir [ERROR] Unknown argument: -u Usage: bash example.sh -n Willy --gender male -a 99 --person_name | -n [Willy] What is your name? --age | -a [Required] --gender | -g [Required] --location | -l [chocolate-factory] insert your location
Final words
I hope that using bargs will assist you in writing a bash script and parsing command line arguments.
Feel free to ask questions, I've already answered a few in this reddit post, so keep 'em coming. The community feedback is what makes open-source projects better, so I urge you to doubt and ask questions! 🙂
Liked this blog post? Thank you! Don't forget to 👏/💟/🐴 and share!
Originally published at https://dev.to on July 24, 2020.