Parsing command line arguments in Bash

5 mins
Published on 24 July 2020

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

  1. 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
    
  2. Creating bargs_vars - do one of the following
    • Create the file bargs_vars, put it in the same folder as bargs.sh
    • Download the existing bargs_vars template
      curl -s -L bargs.link/bargs_vars --output bargs_vars
      
  3. 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
     ---
     ---
    
  4. Add the following line at the beginning of your application

    source bargs.sh "$@"
    
  5. 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!

Related Posts