zsh

ZSH Scripting Lesson: Building Interactive Command-Line Interfaces (CLIs)

ZSH is a highly customizable and feature-rich shell for Unix-like operating systems. It provides advanced scripting capabilities, making it an excellent choice for building CLIs.

Basic ZSH Scripting

Like all scripting languages, we start by adding the shebang line to define the path to the interpreter for the script.

The shebang for ZSH looks something like this:

#!/bin/zsh

The following shows a basic “hello world” in ZSH:

#!/bin/zsh
echo "Hello, World!"

Next, we need to make the script into an executable:

chmod +x cli.zsh

To run the script, we can run the following command:

./cli.zsh

Reading the User Input

One of the major building blocks of interactive CLIs is the ability to require and accept the user input.

In ZSH, we can read the user input using the “read” command:

#!/bin/zsh

echo "Enter your name:"
read name
echo "Hello, $name!"

Menu-Based CLI

Building a menu-based CLI involves presenting the user with options and executing the chosen action.

An example is as follows:

#!/bin/zsh
while true; do
   echo "Menu:"
   echo "1. Option 1"
   echo "2. Option 2"
   echo "3. Quit"
   read choice
   case $choice in
       1)
           echo "You selected Option 1"
           # Add your logic for Option 1 here
           ;;
       2)
           echo "You selected Option 2"
           # Add your logic for Option 2 here
           ;;
       3)
           echo "Goodbye!"
           exit 0
           ;;
       *)
           echo "Invalid choice. Please select a valid option."
           ;;
   esac
done

The previous example presents a menu with three options. Depending on the selected choice, the script performs various actions.

ZSH Parsing: Simple Argument

Look at the following example script that demonstrates using ZSH to parse a basic command-line argument.

Start by creating the script file:

$ touch simple.sh

Add the script code as follows:

#!/usr/bin/env zsh
for arg in "$@"
do
  echo "arg: $arg"
done

Save the file and make it executable:

$ chmod +x simple.sh

We can then run the script and provide the arguments as shown in the following:

./simple.sh MySQL PostgreSQL Redis

Once we run the previous command, we should get an output as shown in the following:

arg: MySQL
arg: PostgreSQL
arg: Redis

As you can see, the previous code iterates over the argument array and prints out the value of each passed argument.

Shift the Positional Arguments

When parsing the arguments, you might need to shuffle the position of the positional arguments to a different position. This is where we can use the “shift” command to achieve this task.

The “shift” command allows us to shift the positional arguments, allowing “$2” to become “$1” and “$3” to become “$2”, and so on.

One of the most common use cases is when you must iterate over all the arguments while omitting the first. Instead of manually parsing and skipping the first one, you can use this “shift” command to solve all those issues.

Take a look at the following example:

#!/usr/bin/env zsh
shift
echo "After shift, arg 1: $1"

Once we run the previous code, we should get the output as follows:

./shift MySQL PostgreSQL Redis

Output:

$ ./shift.sh MySQL PostgreSQL Redis
After shift, arg 1: PostgreSQL

Working with ZSH Flags and Options

The most common use case of command-line options is to specify a given flag or option. This allows us to provide more functionality that can be activated when needed during script execution.

For example, when running a script, you can invoke the “-h” or “—help” flag which allows us to show the help and functionality of the script.

It is good to keep in mind that although the flags and options are used interchangeably, they differ in the form that the options accept as a value in the “while” flags.

An example of a flag is as follows:

./script.sh --help
./script -h

The following is an example of an option:

./script -f filename
./script --file=filename

There you have it!

Error Handling

To extend the functionality and reliability of the script, you should implement the error-handling techniques to handle the errors gracefully.

We can use the “if” statements and exit codes for error handling as demonstrated in the following example:

#!/bin/zsh
if [ $# -ne 2 ]; then
   echo "Usage: $0 <arg1> <arg2>"
   exit 1
fi
arg1="$1"
arg2="$2"

This checks for the return code of a given execution and performs an action on the return value.

Conclusion

This post covers the fundamentals of building the interactive command-line interfaces with features such as user input, argument parsing, error handling, etc.

About the author

John Otieno

My name is John and am a fellow geek like you. I am passionate about all things computers from Hardware, Operating systems to Programming. My dream is to share my knowledge with the world and help out fellow geeks. Follow my content by subscribing to LinuxHint mailing list