Creating Interactive Command-Line Menus in Bash

Creating Interactive Command-Line Menus in Bash

Creating Interactive Command-Line Menus in Bash

 

Introduction

When working with automation scripts, system maintenance, or dev tools, Bash remains one of the most flexible environments available. While plain command-line tools are powerful, making them interactive adds a new level of usability. An interactive menu allows users to make selections and trigger specific commands dynamically — all within the terminal. In this tutorial, we’ll explore how to build interactive command-line menus in Bash using a mix of shell scripting features such as loops, conditional statements, and functions.

1. Building a Basic Menu Structure

The simplest version of a menu in Bash involves displaying options and reading user input with read. The following example creates a basic menu that lets users choose one of three options:

#!/bin/bash

while true; do
    echo "\n=== Main Menu ==="
    echo "1. Show current date"
    echo "2. List files"
    echo "3. Exit"
    read -p "Enter your choice [1-3]: " choice

    case $choice in
        1)
            date
            ;;
        2)
            ls -lh
            ;;
        3)
            echo "Goodbye!"
            break
            ;;
        *)
            echo "Invalid choice. Please try again."
            ;;
    esac
done

Here, we use a while true loop to continuously display the menu until the user chooses to exit. The case statement cleanly manages each possible input.

2. Modularizing Logic with Functions

As menus become larger, using functions helps to keep the code organized and reusable. You can define separate functions for each task, and then call them inside the case structure:

#!/bin/bash

function show_date() {
    echo "Current Date and Time: $(date)"
}

function list_files() {
    echo "Listing contents of $(pwd):"
    ls -lh
}

function system_info() {
    echo "System Info:"
    uname -a
}

while true; do
    echo "\n=== Menu ==="
    echo "1. Show Date"
    echo "2. List Files"
    echo "3. System Info"
    echo "4. Exit"

    read -p "Your choice: " choice

    case $choice in
        1) show_date ;;
        2) list_files ;;
        3) system_info ;;
        4) break ;;
        *) echo "Invalid choice" ;;
    esac
done

Functions make it simple to scale up your script, add error handling, or integrate with external tools later on.

3. Using ‘select’ for Built-in Menus

Bash provides a built-in command, select, that simplifies creating numbered menus automatically. It is especially useful when you don’t want to manage menu numbering manually:

#!/bin/bash

PS3="Please select an option: "

select opt in "Show Date" "List Files" "Exit"; do
    case $REPLY in
        1) date ;;
        2) ls -lh ;;
        3) echo "Exiting..."; break ;;
        *) echo "Invalid choice. Try again." ;;
    esac
done

The select loop handles menu numbering automatically and uses $REPLY to capture the user’s input. You can also customize the PS3 prompt to your liking.

4. Handling Dynamic Commands and External Scripts

You can take interactivity further by dynamically invoking scripts or commands based on user input. Suppose you have multiple automation scripts in a directory — you can create a dynamic selection menu:

#!/bin/bash

scripts=(./scripts/*.sh)
PS3="Choose a script to run: "

select script in "${scripts[@]}" "Exit"; do
    if [[ $REPLY -gt 0 && $REPLY -le ${#scripts[@]} ]]; then
        echo "Running $script..."
        bash "$script"
    elif [[ $REPLY -eq $((${#scripts[@]}+1)) ]]; then
        echo "Goodbye!"
        break
    else
        echo "Invalid choice. Try again."
    fi
done

This menu automatically loads available scripts, saving time for teams maintaining multiple automation routines. It’s dynamic — no need to update the menu manually every time a new script is added.

5. Enhancing UX: Colors and Validation

A professional touch can make CLI menus more readable and friendly. Adding color output using ANSI codes improves usability:

#!/bin/bash

green='\033[0;32m'
red='\033[0;31m'
reset='\033[0m'

while true; do
    echo -e "${green}\n--- Bash Menu ---${reset}"
    echo "1. Check Disk Usage"
    echo "2. Show Memory Usage"
    echo "3. Quit"
    read -p "Choice: " choice

    if ! [[ $choice =~ ^[1-3]$ ]]; then
        echo -e "${red}Error:${reset} Invalid input."
        continue
    fi

    case $choice in
        1) df -h ;;
        2) free -h ;;
        3) echo "Exiting..."; break ;;
    esac
done

Here, we validate the user’s input using a regular expression and add color-coded feedback for errors. These small additions make your Bash menus easier to read and less error-prone.

Conclusion

Interactive command-line menus in Bash are invaluable for simplifying complex automation workflows, user interactions, and script management. By combining loops, conditionals, functions, and even colorized feedback, you can deliver a smooth CLI experience for both developers and administrators. Whether you’re automating server maintenance or providing utilities for developers, adding a friendly interface ensures your scripts are practical, maintainable, and enjoyable to use.

 

Useful links: