Skip to content

unfor19/bargs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

d05b9f1 · Feb 12, 2025
Aug 14, 2020
Aug 14, 2020
Jul 29, 2020
Jul 31, 2020
Aug 21, 2021
Oct 5, 2020
Jul 22, 2020
Feb 12, 2025
Feb 12, 2025
Oct 2, 2020
Feb 12, 2025
Aug 22, 2020

Repository files navigation

bargs

testing

A utility for creating a Bash CLI application.

bargs-demo

Examples

Features

  1. Help Message is auto generated, set bargs > description to update the usage (--help) message

  2. Short and Long Names are supported with name=person_name and short=n

  3. Description Per Argument is supported with description=What is your name?

  4. Flexible Assignment enables passing arguments with the equal sign or a whitespace

    • example.sh --name "Willy Wonka"
    • example.sh --name="Willy Wonka"
  5. Default Value for each argument can be set with default=some-value

    • If default contains whitespaces, use double quotes - default="Willy Wonka"
    • If default starts with a $, then it's a variable
      default=$LANG is evaluted to default=en_US.UTF-8
  6. Allow Environment Variables with allow_env_var=true, if argument is empty then the environment variable will be used. If environment variable is empty, the default will be used

    • Environment variable name must be UPPERCASED, export USERNAME=willywonka
    • Available in your application as $USERNAME or $username
  7. Allow Empty Values with allow_empty=true

  8. Flag Argument with flag=true, if the flag is provided, its value is true - CI=true

  9. Constrain Values is supported with options=first second last, use whitespace as a separator

  10. Prompt for arguments with prompt=true

    • Hide user input with hidden=true
    • Prompt for value confirmation with confirmation=true

Requirements

  • Bash v4.4+
  • Util-Linux - We're printing beautiful stuff with the column command

macOS

brew install util-linux

Ubuntu (Debian)

sudo apt-get -y update && sudo apt-get install -y bsdmainutils

Alpine

apk add --no-cache util-linux bash

CentOS

yum update -y && yum install -y util-linux bash

Windows

Works in Windows-Subsystem-Linux (WSL) using Ubuntu 18.04

More details - Expand/Collapse

Make sure you use dos2unix on all files, see another example here

choco install dos2unix
# ...
dos2unix bargs.sh bargs_vars example.sh tests.sh
# ...
wsl -u root -d Ubuntu-18.04 -- source example.sh

Getting Started

  1. Download bargs.sh (10 kilobytes) and the bargs_vars template

    • Latest version (master)
      curl -sL --remote-name-all bargs.link/{bargs.sh,bargs_vars}
    • Specific release (v1.x.x)
      curl -sL --remote-name-all bargs.link/1.1.4/{bargs.sh,bargs_vars}
  2. Reference to bargs_vars - do one of the following

    • Default behavior - bargs.sh and bargs_vars are in the same folder
    • Specific bargs_vars path - export BARGS_VARS_PATH="${PWD}/path/to/my_bargs_vars", see tests.sh
  3. Edit bargs_vars - Declare arguments/variables, here are some ground rules

    • The delimiter --- is required once at the beginning, and twice in the end
    • Characters which are not supported: =, ~, \, ', "
    • The last variable bargs is necessary, comments below
    • It's best to source bargs at the top of the bash script.
---
name=bargs                                                # DON'T TOUCH!
description=bash example.sh -n Willy --gender male -a 99  # Editable, that's the usage message
default=irrelevant                                        # DON'T TOUCH!
---
---
bargs_vars - Expand/Collpase
---
name=person_name
short=n
description=What is your name?
default="Willy Wonka"
---
name=age
short=a
description=How old are you?
prompt=true
confirmation=true
---
name=gender
short=g
description=male or female?
options=male female
prompt=true
---
name=location
short=l
description=Where do you live?
default="chocolate factory"
---
name=favorite_food
short=f
allow_empty=true
options=chocolate pizza
description=chocolate or pizza?
---
name=secret
short=s
default=!@#%^&*?/.,[]{}+-|
description=special characters
---
name=language
short=lang
default=$LANG
description=default value can be a variable
---
name=password
short=p
prompt=true
hidden=true
confirmation=true
description=What is your password?
---
name=happy
short=hp
flag=true
description=Flag for indicating that you are happy
---
name=ci
short=ci
flag=true
description=Flag for indicating it is a CI/CD process
---
name=username
short=un
allow_env_var=true
description=Username fetched from environment variable
default=willywonka
---
name=bargs
description=bash example.sh -n Willy --gender male -a 99
default=irrelevant
---
---
  1. Add one of the following lines at the beginning of your application (see Usage below)

    • bargs.sh is in the root folder of your project (just like in this repo)
      source "${PWD}"/"$(dirname ${BASH_SOURCE[0]})"/bargs.sh "$@"
    • bargs.sh is in a subfolder, for example tools
      source "${PWD}"/"$(dirname ${BASH_SOURCE[0]})"/tools/bargs.sh "$@"
  2. The arguments are now available as environment variables, both lowercased and UPPERCASED (see Usage below)

Usage

Using the bargs_vars above in our application - example.sh

#!/bin/bash
source "${PWD}"/"$(dirname ${BASH_SOURCE[0]})"/bargs.sh "$@"

echo "
Name:                  ~ $person_name
Age:                   ~ $age
Gender:                ~ $gender
Location:              ~ $location
Favorite food:         ~ $favorite_food
Secret:                ~ $secret
Password:              ~ $password
OS Language:           ~ $language
I am happy:            ~ $happy
CI Process:            ~ $CI
Uppercased var names:  ~ $PERSON_NAME, $AGE years old, from $LOCATION
Username from env var: ~ $username " \
    | column -t -s "~"

Usage output

Results after running tests.sh - Expand/Collapse
-------------------------------------------------------
[LOG] Bargs Vars Path - Should pass
[LOG] Executing: source example.sh -a 33 --gender male -p mypassword
[LOG] Output:

Name:                     Oompa Looma
Age:                      33
Gender:                   male
Location:                 chocolate factory
Favorite food:            
Secret:                   !@#%^&*?/.,[]{}+-|
Password:                 mypassword
OS Language:              C.UTF-8
I am happy:               
CI Process:               
Uppercased var names:     Oompa Looma, 33 years old, from chocolate factory
Username from env var:    runner 

[LOG] Test passed as expected
-------------------------------------------------------
[LOG] Help Menu - Should pass
[LOG] Executing: source example.sh -h
[LOG] Output:


Usage: bash example.sh -n Willy --gender male -a 99

	--person_name    |  -n     [Willy Wonka]         What is your name?
	--age            |  -a     [REQUIRED]            How old are you?
	--gender         |  -g     [REQUIRED]            male or female?
	--location       |  -l     [chocolate factory]   Where do you live?
	--favorite_food  |  -f     []                    chocolate or pizza?
	--secret         |  -s     [!@#%^&*?/.,[]{}+-|]  special characters
	--language       |  -lang  [C.UTF-8]             default value can be a variable
	--password       |  -p     [REQUIRED]            What is your password?
	--happy          |  -hp    [FLAG]                Flag for indicating that you are happy
	--ci             |  -ci    [FLAG]                Flag for indicating it is a CI/CD process
	--username       |  -un    [willywonka]          Username fetched from environment variable

[LOG] Test passed as expected
-------------------------------------------------------
[LOG] Default Values - Should pass
[LOG] Executing: source example.sh -a 99 --gender=male -p mypassword
[LOG] Output:

Name:                     Willy Wonka
Age:                      99
Gender:                   male
Location:                 chocolate factory
Favorite food:            
Secret:                   !@#%^&*?/.,[]{}+-|
Password:                 mypassword
OS Language:              C.UTF-8
I am happy:               
CI Process:               
Uppercased var names:     Willy Wonka, 99 years old, from chocolate factory
Username from env var:    runner 

[LOG] Test passed as expected
-------------------------------------------------------
[LOG] New Values - Should pass
[LOG] Executing: source example.sh -a 23 --gender male -l=neverland -n meir -p mypassword
[LOG] Output:

Name:                     meir
Age:                      23
Gender:                   male
Location:                 neverland
Favorite food:            
Secret:                   !@#%^&*?/.,[]{}+-|
Password:                 mypassword
OS Language:              C.UTF-8
I am happy:               
CI Process:               
Uppercased var names:     meir, 23 years old, from neverland
Username from env var:    runner 

[LOG] Test passed as expected
-------------------------------------------------------
[LOG] Valid Options - Should pass
[LOG] Executing: source example.sh -a 23 --gender male -l neverland -n meir -f pizza -p=mypassword
[LOG] Output:

Name:                     meir
Age:                      23
Gender:                   male
Location:                 neverland
Favorite food:            pizza
Secret:                   !@#%^&*?/.,[]{}+-|
Password:                 mypassword
OS Language:              C.UTF-8
I am happy:               
CI Process:               
Uppercased var names:     meir, 23 years old, from neverland
Username from env var:    runner 

[LOG] Test passed as expected
-------------------------------------------------------
[LOG] Special Characters - Should pass
[LOG] Executing: source example.sh -a 99 --gender male -s MxTZf+6KHaAQltJWipe1oVRy -p mypassword
[LOG] Output:

Name:                     Willy Wonka
Age:                      99
Gender:                   male
Location:                 chocolate factory
Favorite food:            
Secret:                   MxTZf+6KHaAQltJWipe1oVRy
Password:                 mypassword
OS Language:              C.UTF-8
I am happy:               
CI Process:               
Uppercased var names:     Willy Wonka, 99 years old, from chocolate factory
Username from env var:    runner 

[LOG] Test passed as expected
-------------------------------------------------------
[LOG] Use Flag - Should pass
[LOG] Executing: source example.sh -a 23 --gender male --happy -p mypassword -ci
[LOG] Output:

Name:                     Willy Wonka
Age:                      23
Gender:                   male
Location:                 chocolate factory
Favorite food:            
Secret:                   !@#%^&*?/.,[]{}+-|
Password:                 mypassword
OS Language:              C.UTF-8
I am happy:               true
CI Process:               true
Uppercased var names:     Willy Wonka, 23 years old, from chocolate factory
Username from env var:    runner 

[LOG] Test passed as expected
-------------------------------------------------------
[LOG] Empty Argument - Should fail
[LOG] Executing: source example.sh -a 99 --gender -p mypassword
[LOG] Output:

[HINT] Valid options: male OR female
[ERROR] Invalid value "-p" for the argument "gender"

Usage: bash example.sh -n Willy --gender male -a 99

	--person_name    |  -n     [Willy Wonka]         What is your name?
	--age            |  -a     [REQUIRED]            How old are you?
	--gender         |  -g     [REQUIRED]            male or female?
	--location       |  -l     [chocolate factory]   Where do you live?
	--favorite_food  |  -f     []                    chocolate or pizza?
	--secret         |  -s     [!@#%^&*?/.,[]{}+-|]  special characters
	--language       |  -lang  [C.UTF-8]             default value can be a variable
	--password       |  -p     [REQUIRED]            What is your password?
	--happy          |  -hp    [FLAG]                Flag for indicating that you are happy
	--ci             |  -ci    [FLAG]                Flag for indicating it is a CI/CD process
	--username       |  -un    [willywonka]          Username fetched from environment variable

[LOG] Test failed as expected
-------------------------------------------------------
[LOG] Unknown Argument - Should fail
[LOG] Executing: source example.sh -a 99 -u meir -p mypassword
[LOG] Output:

[ERROR] Unknown argument "-u"

Usage: bash example.sh -n Willy --gender male -a 99

	--person_name    |  -n     [Willy Wonka]         What is your name?
	--age            |  -a     [REQUIRED]            How old are you?
	--gender         |  -g     [REQUIRED]            male or female?
	--location       |  -l     [chocolate factory]   Where do you live?
	--favorite_food  |  -f     []                    chocolate or pizza?
	--secret         |  -s     [!@#%^&*?/.,[]{}+-|]  special characters
	--language       |  -lang  [C.UTF-8]             default value can be a variable
	--password       |  -p     [REQUIRED]            What is your password?
	--happy          |  -hp    [FLAG]                Flag for indicating that you are happy
	--ci             |  -ci    [FLAG]                Flag for indicating it is a CI/CD process
	--username       |  -un    [willywonka]          Username fetched from environment variable

[LOG] Test failed as expected
-------------------------------------------------------
[LOG] Invalid Options - Should fail
[LOG] Executing: source example.sh -a 23 --gender male -l neverland -n meir -f notgood -p mypassword
[LOG] Output:

[HINT] Valid options: chocolate OR pizza
[ERROR] Invalid value "notgood" for the argument "favorite_food"

Usage: bash example.sh -n Willy --gender male -a 99

	--person_name    |  -n     [Willy Wonka]         What is your name?
	--age            |  -a     [REQUIRED]            How old are you?
	--gender         |  -g     [REQUIRED]            male or female?
	--location       |  -l     [chocolate factory]   Where do you live?
	--favorite_food  |  -f     []                    chocolate or pizza?
	--secret         |  -s     [!@#%^&*?/.,[]{}+-|]  special characters
	--language       |  -lang  [C.UTF-8]             default value can be a variable
	--password       |  -p     [REQUIRED]            What is your password?
	--happy          |  -hp    [FLAG]                Flag for indicating that you are happy
	--ci             |  -ci    [FLAG]                Flag for indicating it is a CI/CD process
	--username       |  -un    [willywonka]          Username fetched from environment variable

[LOG] Test failed as expected
-------------------------------------------------------
[LOG] Missing bargs_vars - Should fail
[LOG] Executing: source example.sh -h
[LOG] Output:

[ERROR] Make sure bargs_vars is in the same folder as bargs.sh
	Another option - export BARGS_VARS_PATH="/path/to/my_bargs_vars"

[LOG] Test failed as expected

Package your application with Docker

You can use Docker to package your Bash script as a Docker image, see the following example

  1. Clone this repository

  2. Build the image, see Dockerfile.example, tag it bargs:example

    docker build -f Dockerfile.example -t bargs:example .
  3. Run a container that is based on the image above

    docker run --rm -it bargs:example -a 23 -g male

Use this repository as a template

Thinking of writing a new Bash script? Hit the Use this template button and get a fully working example of bargs, including GitHub Actions workflows.

Contributing

Report issues/questions/feature requests on the Issues section.

Pull requests are welcome! These are the steps:

  1. Fork this repo
  2. Create your feature branch from master (git checkout -b my-new-feature)
  3. Add the code of your new feature
  4. Run tests on your code, feel free to add more tests
    bash tests.sh
    ... # All good? Move on to the next step
  5. Commit your remarkable changes (git commit -am 'Added new feature')
  6. Push to the branch (git push --set-up-stream origin my-new-feature)
  7. Create a new Pull Request and provide details about your changes

Authors

Created and maintained by Meir Gabay

License

This project is licensed under the MIT License - see the LICENSE file for details