Sometimes, I need a simple menu in bash, but I don’t want to spend a good deal of time coding for one.
Bash has a built-in command called select which gets the job done. To demonstrate this command, I am going to write a short bash script. This script lists all the files in the current directory, then prompts the user to make a choice. If the choice is valid, it invokes the editor on the file. It will ignore any invalid choice. Below is the source for that script:
# Displays a list of files in current directory and prompt for which
# file to edit
# Set the prompt for the select command
PS3="Type a number or 'q' to quit: "
# Create a list of files to display
fileList=$(find . -maxdepth 1 -type f)
# Show a menu and ask for input. If the user entered a valid choice,
# then invoke the editor on that file
select fileName in $fileList; do
if [ -n "$fileName" ]; then
Line 6 – By default the select commmand uses ‘#?’ as a menu prompt. If the variable PS3 is defined, it will use that variable instead.
Line 9 – The find command retrieves a list of files in the current directory. The script then stores the result in the variable fileList
Line 13 to 18 – The select .. do .. done command displays a menu using $fileList as a list of items.
Line 14 to 16 – This block of code check if the user’s choice was valid and invoke the editor accordingly
Line 17 – The select command acts like an endless loop unless a break command is encountered
Below is a sample run
Type a number or 'q' to quit: 3
If you are reading this far, I hope you detected my hack (hint, look at the PS3 prompt). By experimenting with select, I found out that if the user entered an invalid choice (i.e. a letter ‘q’ instead of an integer) then select will set the control variable ($fileName in this case) to empty. Taking advantage of this feature (or bug?), I designed the prompt and check for non-empty variable (line 14-16) before invoking the editor.
The select command is easy to use, but it save the script writers from the tedious job of displaying the menu, the prompt, then ask for the user’s input. The only caveat programmers need to watch out for is the lack of input validation so be sure to check your control variable before using it.