In this week’s Bash Scripting Sunday, we’re diving into creating simple interactive menus in Bash.
If you’ve ever wanted to give your scripts a bit of user interactivity—like choosing from a list of options—you’ll love this one.
🧭 Why Use Menus?
Menus are great when:
- You want to prompt the user for input from a list
- You’re writing utility scripts with multiple actions
- You want something more user-friendly than raw
read
input
🔧 The Basics: select
and PS3
Bash comes with a built-in construct called select
that makes menus easy.
Here’s the simplest form:
#!/usr/bin/env bash
PS3="Choose an option: "
options=("Start" "Stop" "Restart" "Quit")
select opt in "${options[@]}"; do
case $opt in
"Start")
echo "Starting..."
;;
"Stop")
echo "Stopping..."
;;
"Restart")
echo "Restarting..."
;;
"Quit")
echo "Exiting."
break
;;
*) echo "Invalid option $REPLY";;
esac
done
🧵 What’s Happening?
PS3
sets the prompt string.select
automatically prints a numbered list.- The user’s selection is stored in the variable
$opt
. - The number they typed is stored in
$REPLY
.
Try it out! It’ll look like this:
1) Start
2) Stop
3) Restart
4) Quit
Choose an option:
🧽 Cleaning It Up (Optional Enhancements)
Here are a few nice touches you can add:
1. Clear the screen before showing the menu
clear
Or use tput clear
if you want to stay portable.
2. Repeat the menu until “Quit”
Wrap the select
in a while true
loop and break only on Quit:
while true; do
select opt in "${options[@]}"; do
case $opt in
"Quit") break 2 ;;
...
esac
done
done
3. Add colours
Add colour using ANSI escape codes:
RED="\e[31m"
RESET="\e[0m"
echo -e "${RED}Error: Invalid choice${RESET}"
🧠 Tips & Gotchas
select
works best in an interactive terminal – not ideal for scripts meant to run non-interactively.- Always validate the input inside the
case
, even if it looks correct. select
does not loop automatically – you control the loop.
🧪 Practical Use Case: Simple Admin Script
Here’s an example admin helper:
#!/usr/bin/env bash
PS3="Action: "
options=("Update System" "View Disk Usage" "Reboot" "Exit")
select opt in "${options[@]}"; do
case $opt in
"Update System")
sudo apt update && sudo apt upgrade -y
;;
"View Disk Usage")
df -h
;;
"Reboot")
echo "Rebooting..."
sudo reboot
;;
"Exit")
break
;;
*) echo "Invalid option: $REPLY";;
esac
done
🧵 Summary
- ✅
select
is a great way to build quick, interactive menus in Bash. - ✅ Use
PS3
to customise the prompt. - ✅ Combine with loops and
case
to build functional CLI menus. - ✅ Great for small tools, helpers, or user-facing scripts.
Next week: We’ll cover how to safely handle temporary files in your scripts using traps and mktemp
.
Until then, happy scripting! 🐚
📦 Bonus: Using dialog
for Fancy Menus
If you want a more visual and interactive experience, dialog
is a fantastic tool that provides full-screen menus, message boxes, and input prompts in the terminal.
Install it with:
sudo apt install dialog # Debian/Ubuntu
sudo dnf install dialog # Fedora
sudo pacman -S dialog # Arch
Here’s how you can create a simple menu using dialog
:
#!/usr/bin/env bash
HEIGHT=15
WIDTH=40
CHOICE_HEIGHT=4
TITLE="System Actions"
MENU="Choose one of the following:"
OPTIONS=(
1 "Update System"
2 "View Disk Usage"
3 "Reboot"
4 "Exit"
)
CHOICE=$(dialog --clear \
--backtitle "Admin Menu" \
--title "$TITLE" \
--menu "$MENU" \
$HEIGHT $WIDTH $CHOICE_HEIGHT \
"${OPTIONS[@]}" \
2>&1 >/dev/tty)
clear
case $CHOICE in
1)
sudo apt update && sudo apt upgrade -y
;;
2)
df -h
;;
3)
echo "Rebooting..."
sudo reboot
;;
4)
echo "Exiting."
;;
esac
💡 Why Use dialog
?
- 📋 Easy to use with clear prompts
- 🖥️ Feels more like a proper UI
- ✅ Great for users unfamiliar with terminal prompts
⚠️ Just keep in mind:
- It requires the
dialog
package to be installed.- Works best in a full-featured terminal (not ideal for limited environments).