loading...
Cover image for parsing command line arguments in Bash

parsing command line arguments in Bash

unfor19 profile image Meir Gabay Updated on ・4 min read

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 ☝️ 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
  1. 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
    
  2. 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
    ---
    ---
  1. Add the following line at the beginning of your application
   source bargs.sh "$@"
  1. 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!

Posted on by:

unfor19 profile

Meir Gabay

@unfor19

I'm passionate about studying and teaching. DevOps Consultant @ ProdOps.io

Discussion

markdown guide