Bash Select (Make Menus)

By 

Updated on

6 min read

Bash select

The select construct in Bash allows you to generate interactive menus in shell scripts. It displays a numbered list of items and prompts the user to make a selection.

In this guide, we will cover the syntax of the select construct and show you how to use it with practical examples.

Syntax

The select construct has almost the same syntax as the for loop:

txt
select ITEM in [LIST]
do
  [COMMANDS]
done

The [LIST] can be a series of strings separated by spaces, a range of numbers, output of a command, an array, and so on.

When the select construct is invoked, each item from the list is printed to standard error, preceded with a number.

If the user enters a number that corresponds to one of the displayed items, then the value of [ITEM] is set to that item. The selected number is stored in the variable REPLY. If the user input is empty, the prompt and the menu list are displayed again.

The select loop will continue to run and prompt for user input until the break command is executed.

The PS3 Prompt

A custom prompt for the select construct can be set using the PS3 environment variable . If PS3 is not set, the default prompt is #? .

Examples

The following examples show how select is commonly used in bash scripts.

Basic Menu

This script displays a list of characters and prints the selection:

sh
#!/bin/bash

PS3="Enter a number: "

select character in Sheldon Leonard Penny Howard Raj
do
    echo "Selected character: $character"
    echo "Selected number: $REPLY"
done

The script displays a menu with an accompanying number and the PS3 prompt. When the user enters a number, the script prints the selected character and number:

output
1) Sheldon
2) Leonard
3) Penny
4) Howard
5) Raj
Enter a number: 3
Selected character: Penny
Selected number: 3
Enter a number:

Using Select with Case

Usually, select is used in combination with case or if statements to act on the user’s choice.

The following script is a simple calculator that prompts the user for input and performs basic arithmetic operations:

sh
#!/bin/bash

PS3="Select the operation: "

select opt in add subtract multiply divide quit; do

  case $opt in
    add)
      read -p "Enter the first number: " n1
      read -p "Enter the second number: " n2
      echo "$n1 + $n2 = $(($n1+$n2))"
      ;;
    subtract)
      read -p "Enter the first number: " n1
      read -p "Enter the second number: " n2
      echo "$n1 - $n2 = $(($n1-$n2))"
      ;;
    multiply)
      read -p "Enter the first number: " n1
      read -p "Enter the second number: " n2
      echo "$n1 * $n2 = $(($n1*$n2))"
      ;;
    divide)
      read -p "Enter the first number: " n1
      read -p "Enter the second number: " n2
      echo "$n1 / $n2 = $(($n1/$n2))"
      ;;
    quit)
      break
      ;;
    *)
      echo "Invalid option $REPLY"
      ;;
  esac
done

When the script is executed, it displays the menu and the PS3 prompt. The user selects an operation and enters two numbers. Depending on the input, the script prints the result. The loop continues until the user selects quit:

output
1) add
2) subtract
3) multiply
4) divide
5) quit
Select the operation: 1
Enter the first number: 4
Enter the second number: 5
4 + 5 = 9
Select the operation: 9
Invalid option 9
Select the operation: 5

One drawback of this script is that it works only with integers. Here is an improved version that uses bc to support floating-point numbers. The repetitive code is grouped inside a function :

sh
#!/bin/bash

calculate () {
  read -p "Enter the first number: " n1
  read -p "Enter the second number: " n2
  echo "$n1 $1 $n2 = " $(bc -l <<< "$n1$1$n2")
}

PS3="Select the operation: "

select opt in add subtract multiply divide quit; do

  case $opt in
    add)
      calculate "+";;
    subtract)
      calculate "-";;
    multiply)
      calculate "*";;
    divide)
      calculate "/";;
    quit)
      break;;
    *)
      echo "Invalid option $REPLY";;
  esac
done
output
1) add
2) subtract
3) multiply
4) divide
5) quit
Select the operation: 4
Enter the first number: 8
Enter the second number: 9
8 / 9 =  .88888888888888888888
Select the operation: 5

Using Select with an Array

You can pass an array as the list of items to select:

sh
#!/bin/bash

options=("Start" "Stop" "Restart" "Status" "Quit")

PS3="Select an action: "

select opt in "${options[@]}"; do
  case $opt in
    Start|Stop|Restart)
      echo "Performing: $opt"
      ;;
    Status)
      echo "Service is running"
      ;;
    Quit)
      echo "Exiting."
      break
      ;;
    *)
      echo "Invalid option $REPLY"
      ;;
  esac
done

Selecting Files from a Directory

The select construct can be combined with command output to create a file picker. The following script lists all .sh files in the current directory and lets the user choose one to execute:

sh
#!/bin/bash

PS3="Select a script to run: "

select file in *.sh; do
  if [[ -n "$file" ]]; then
    echo "Running $file..."
    bash "$file"
    break
  else
    echo "Invalid selection"
  fi
done

If the directory contains backup.sh, deploy.sh, and test.sh, the output looks like:

output
1) backup.sh
2) deploy.sh
3) test.sh
Select a script to run: 2
Running deploy.sh...

Confirmation Prompt

A simple yes/no confirmation menu:

sh
#!/bin/bash

PS3="Are you sure? "

select answer in Yes No; do
  case $answer in
    Yes)
      echo "Confirmed."
      break
      ;;
    No)
      echo "Cancelled."
      break
      ;;
    *)
      echo "Please select 1 or 2."
      ;;
  esac
done

Quick Reference

ElementDescription
select VAR in LISTCreate a menu from LIST
$REPLYHolds the number the user entered
$VARHolds the selected item text
PS3Custom prompt (default: #? )
breakExit the select loop
*) ...Handle invalid selections in case

FAQ

How do I change the select prompt?
Set the PS3 variable before the select construct. For example, PS3="Choose an option: ". If PS3 is not set, the default prompt #? is used.

How do I exit a select loop?
Use the break command. Without it, the select loop runs indefinitely and keeps prompting the user for input.

What happens when the user enters an invalid number?
The ITEM variable is set to an empty string. Use the *) pattern in a case statement to handle invalid selections.

Can I use select with command output?
Yes. For example, select file in $(ls *.txt) creates a menu from all .txt files. However, it is better to use a glob pattern like select file in *.txt to correctly handle filenames with spaces.

What is the difference between $REPLY and the select variable?
$REPLY contains the raw number the user typed. The select variable (e.g., $opt) contains the corresponding text from the list. If the user enters an invalid number, the select variable is empty but $REPLY still holds the entered value.

Conclusion

The select construct allows you to generate interactive menus in shell scripts. It is commonly used with case statements to perform different actions based on the user’s selection.

If you have any questions, feel free to leave a comment below.

Tags

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page