Building Command-line Tools: Bash Edition

InRhythm™
InRhythm
Published in
3 min readDec 3, 2018

Bash is my go-to language for building quick command-line tools, but it is also amazing at building extendable tools for wrapping software. A command-line tool with fully documented tags can make your software/code more user-friendly, and that gets your repo cloned. It’s no coincidence that Bash was one of the languages I listed in my Top 5 Languages to learn for 2019. Check it out when you get a chance!

The Situation

So let’s start off with something common: the “finished” piece of software (by finished, I mean software that works). This can be software of any category, but for this exercise let’s assume it’s a web service that can run locally on a computer. We want to give users a few options:

  • User should be able to check if they have all the necessary software to run the service (Maven, Gradle, Node, etc.)
  • User should be able to choose the port the service should run on
  • User should be able to see a help menu

That’s a good amount of features for now, but let’s see how a requirement looks as a raw command:

User should be able to check if they have all necessary software to run the service (Maven, Gradle, Node, etc)

command mvn -v || echo "Maven is not installed" && command node -v || echo "Node is not installed" &&

command gradle -v || echo "Gradle is not installed"

That’s a lot of commands just to get a rundown of what exists. Expecting users to write this out makes your code less appealing. To show how much we can simplify this, we’ll be updating this repo with our command line tool.

The Solution

This is a simple spring boot service, so our wrapper is also going to be pretty simple. Let’s start with a simple shell file; we’ll call it “funky.sh”. From our user requirements, we only have one requirement that needs user input: “User should be able to choose the port the service should run on.”

We’ll have a standard variable to handle that input:

Next, we will loop over the arguments passed, put them into a variable “$1”, then case switch based on value:

Let’s go over what’s happening here:

  • while test: — allows execution of code over a period where a condition evaluates to true
  • $ #: This is a variable that holds the number of arguments passed to the script
  • $# -gt 0: Our condition which “while test” checks. This condition translated means “while the count of arguments is greater than 0, evaluate to true”
  • while test $# -gt 0; : This is our loop which is used to run our inner “do” block.
  • case “$1” in: Simple switch case, that will match the variable “$1” to one of the execution blocks, -port), -check), -help). If it matches to none of these, it evaluates at the “)” block.
  • shift: Moves the reference of $1, to the next variable and lowers the value of $#.

For the tags of -help, -check, and default case, we exit because the script doesn’t need to run the service. For our -port case, we do need to execute some code on a passed variable. So let’s first do some logic checks before we run the script:

With this code, we are using the -z and [[ ]] to check if the variable is still empty. Earlier in our switch case, we assign it a value if the -port tag is available; however, that doesn’t guarantee the variable isn’t empty. If it is, we will just run it on a default port.

And that’s all there is to it. There are plenty of ways to make this script better — like adding a check to port ensuring its a number — but that is just an addition to logic. The template for making a command line tool in Bash pretty simple, and I hope this helps you in your future projects. Below is the gist of what the script looks like and the Github repo, in which you can try the script out:

The link to the Github repo can be found here.

Thank you so much for reading, and continue to build that cache!

Originally published at www.inrhythm.com.

--

--

InRhythm™
InRhythm

We are Knowledge Driven, Agile Mobile and Web Consultants. 🚀