Check for invalid input in a menu - bash

I am making a script where the user selects a number 1-5 and it will loop until the user enters 5. I don't want to use the exit command. I wanted to check to make sure the user doesn't enter anything but 1-5 and if they do display invalid input.
any help would be appreciated
#!/bin/bash
PS3='Please enter your choice: '
options=("1.Move empty files" "2.Check file size" "3.Which files is newer" "4.File check rwx" select opt in "${options[#]}")
while($opt != 5); do
case $opt in
"Option 1")
echo "you chose choice 1"
;;
"Option 2")
echo "you chose choice 2"
;;
"Option 3")
echo "you chose choice 3"
;;
"Option 4")
echo "you chose choice 3"
;;
"Option 5")
break
;;
) echo invalid input;;

You seem confused. I don't even know where to begin correcting whatever misconceptions you have about how this works
In your original code the way you set options is unlikely to do anything useful.
options=("1.Move empty files" "2.Check file size" "3.Which files is newer" "4.File check rwx" select opt in "${options[#]}"
printf '%s\n' "${options[#]}"
This will emit
1.Move empty files
2.Check file size
3.Which files is newer
4.File check rwx
select
opt
in
The select command will not have been executed.
Here's something that does what you seem to want.
options=(
'Move empty files'
'Check file size'
'Which file is newer'
'File check rwx'
)
PS3='Please enter your choice: '
select opt in "${options[#]}" ; do
[[ -n $opt ]] && break || {
echo "invalid input"
}
done
echo "user chose '$opt'"
You could go with a while and case solution and get nearly the same results e.g.:
options=(
'Move empty files'
'Check file size'
'Which file is newer'
'File check rwx'
)
for (( i=0 ; i < ${#options[#]} ; i++ )) ; do
printf '%d) %s\n' $((i+1)) "${options[$i]}"
done
while true ; do
read -p 'Please enter your choice: ' opt
case "$opt" in
[1-5])
opt="${options[$opt]}"
break
;;
*)
echo "invalid input"
;;
esac
done
echo "user chose '$opt'"
But you don't need both and, as you can see, using select is much simpler.

Related

fill variable from bash menu

Here is a pretty straight forward menu:
VAR=""
PS3='Make a selection: '
options=("opt 1" "opt 2" "opt 3" "Quit")
select opt in "${options[#]}"
do
case $opt in
"opt 1")
echo "opt 1 selected"
;;
"opt 2")
echo "opt 2 selected"
;;
"opt 3")
echo "opt 3 selected"
;;
"Quit")
break
;;
*) echo "invalid option $REPLY";;
esac
done
I would like for each option to add the following:
for instance if "opt 1" is selected:
[[ $(VAR) ]] && VAR="${VAR}\|123" || VAR=123
for "opt 2", 456
for "opt 3", 789
At the end, we should have:
VAR=123\|789 if "opt 1" and "opt 3" have been choosen
or
VAR=789 if only "opt 3" have been choosen.
The issue I am facing with is that my syntax to populate VAR does not work: VAR stays empty after having exited menu.
Thanx folks!
Following your approach.
You are missing to export the variable VAR in order to be available once the script has been executed.
VAR=""
PS3='Make a selection: '
options=("opt 1" "opt 2" "opt 3" "Quit")
select opt in "${options[#]}"
do
case $opt in
"opt 1")
echo "opt 1 selected"
VAR="${VAR}\|123"
;;
"opt 2")
echo "opt 2 selected"
VAR="${VAR}\|456"
;;
"opt 3")
echo "opt 3 selected"
VAR="${VAR}\|789"
;;
"Quit")
break
;;
*) echo "invalid option $REPLY"
echo $VAR ;;
esac
done
export VAR
However, export only applies to child-processes. As workaround, you can execute the script as . test.sh
Example of output:
[10:08:18][/]# . test.sh
1) opt 1
2) opt 2
3) opt 3
4) Quit
Make a selection: 1
opt 1 selected
Make a selection: 2
opt 2 selected
Make a selection: 4
[10:08:18][/]#echo $VAR
\|123\|456
You can modify the way to assign the value of the variable for having the desired output.
By adding the dot as way of execution, you are sourcing the variable. More information here: Export variable from bash
Hope this helps you a little. It's less programming than with a case in it.
#! /bin/bash
VAR=""
# Declare options and values for options
declare -A OPTIONS
OPTIONS[opt 1]="123"
OPTIONS[opt 2]="456"
OPTIONS[opt 3]="789"
echo "Options: ${!OPTIONS[#]}"
while read -r -p "Make a selection: " opt; do
# If opt becomes quit or Quit, break from loop.
! [[ $opt =~ (Q|q)uit ]] || break
if [[ ${OPTIONS[$opt]}x == "x" ]]; then
echo "$opt unknown"
else
VAR+=${OPTIONS[$opt]}
fi
done
echo $VAR
exit 0

the select menu does not behave as it is expected

I'm new to bash. I want to have a select menu in bash. It has four options. Here is the code:
#!/bin/bash
PS3='Please enter your choice: '
while true; do
clear
options=("Option 1" "Option 2" "Option 3" "Exit")
select opt in "${options[#]}"
do
case $opt in
"Option 1")
echo "you chose choice $REPLY which is $opt"
break
;;
"Option 2")
echo "you chose choice $REPLY which is $opt"
break
;;
"Option 3")
echo "you chose choice $REPLY which is $opt"
firefox http://localhost:8000/browser/
break
;;
"Exit")
break 2
;;
*) echo "invalid option $REPLY";;
esac
done
read -p "Press [Enter] key to continue..."
done
Here is the output:
1) Option 1
2) Option 2
3) Option 3
4) Exit
Please enter your choice: 1
#you chose choice 1 which is Option 1
Press [Enter] key to continue...
This code works perfectly fine, except when I press 3. In this case after printing the message I want, the browser is opened using this command:
firefox http://localhost:8000/browser/
after opening the browser, I expect my code to display this message:
Press [Enter] key to continue...
but it doesn't until I close the browser. What's wrong?
What's wrong?
Great code!
If you want to run the process firefox in the background just add & to the end of the command.
echo "you chose choice $REPLY which is $opt"
firefox http://localhost:8000/browser/ &
break

Select case menu not working

I have the following select menu.
#!/bin/bash
PS3='Please enter your choice(1-4): '
options=("First Install" "Add cilent" "Delete Cilent" "Quit")
select opt in "${options[#]}"
do
case $opt in
"First Install")
newinstall
break
;;
"Add cilent")
add_client
break
;;
"Delete Cilent")
delete_client
break
;;
"Quit")
break
;;
*) echo invalid option;;
esac
done
The issue is that when i enter 2 i get invalid option message whereas all other cases work.
To avoid typos I suggest to use strings of array options only once in your code. Replace "First Install") by "${options[0]}") and "Add cilent") by "${options[1]}") etc.:
#!/bin/bash
PS3='Please enter your choice(1-4): '
options=("First Install" "Add cilent" "Delete Cilent" "Quit")
select opt in "${options[#]}"
do
case $opt in
"${options[0]}")
newinstall
break
;;
"${options[1]}")
add_client
break
;;
"${options[2]}")
delete_client
break
;;
"${options[3]}")
break
;;
*) echo invalid option;;
esac
done

How to put break statement inside a condition which is inside a switch case in korn script

I am writing a korn script to process some fixed/user provided input. I am not able to run this script as I am getting syntax error `)' unexpected. I am thinking that it is because I am using a break inside the if statement, where the if is inside a switch case. I have just picked up scripting last week and would really appreciate any help on this.
P.S There is a reason for using korn script.
#!/usr/bin/ksh93
typeset -A fileset_list #fileset_list is associative
fileset_list=([All filesets]="A B C D E"
[A]=AA
[B]=BB
[C]="CC CCC CCCC CCCC"
[D]=DD
[E]="EE EEE EEEE EEEE EEEEE"
)
fileset="All filesets"
echo "Recent update has found following unsupported filesets on the system:\n${fileset_list["All filesets"]}"
echo "Do you want to delete all the listed filesets along with their dependencies Y/N"
while true; do
read yn
case $yn in
[Yy]* )
set -A delete_list ${fileset_list["All filesets"]}
uninstall_fun
break;;
[Nn]* )
echo "Do you want to delete the partial list Y/N"
while true; do
read y_n
case $y_n in
[Yy]* ) echo "Enter the space separated filesets from the above list for deletion"
read user_list
echo "You have entered $user_list\nIs the list correct Y/N"
read selection
if [[ $selection == [Yy]* ]]
then
set -A delete_list $user_list
uninstall_fun
break;; #<<<<ISSUE
else
echo "Do you want to re-enter list Y/N" #<<<<<need this to go back and read y_n
fi
# break;;
[Nn]* )
break;;
* ) echo "Please answer yes(y) or no(n).";;
esac
done
break;;
* ) echo "Please answer yes(y) or no(n).";;
esac
done
uninstall_fun(){
echo "In uninstall_fun"
}
The ;; is used at the end of each case block. You had one in the middle of the if statement, but the case block is not finished yet.
The line with break;; # <<<<ISSUE should become break # without ;;,
and the line # break;; should be ;;.
[Yy]* ) echo "Enter the space separated filesets from the above list for deletion"
read user_list
echo "You have entered $user_list\nIs the list correct Y/N"
read selection
if [[ $selection == [Yy]* ]]
then
set -A delete_list $user_list
uninstall_fun
break # Without ;;
else
echo "Do you want to re-enter list Y/N" #<<<<<need this to go back and read y_n
fi
;; # Needed here
[Nn]* )

I need to edit the bash script to select a letter to do separate commands

I am not sure what step is next in the process to get the commands to do what I want. I want to select a letter to do a command. Right now it lets you use any letter.
#!/bin/bash
echo "Please select l to list files of a directory, b to backup a file or directory, u to edit a user's password, and x to exit the script"
read $answer
if [ $answer="l" ]; then
printf "Please select folder:\n"
select d in */; do test -n "$d" && break; echo ">>> Invalid Selection"; done
cd "$d" && pwd
ls
fi
Use a case statement
case expression in
pattern1 )
statements ;;
pattern2 )
statements ;;
...
esac
e.g:
case $arg in
l)
printf "Please select folder:\n"
select d in */; do test -n "$d" && break; echo ">>> Invalid Selection"; done
cd "$d" && pwd
ls
;;
cmd1)
echo "Some other cmds line 1"
echo "Some other cmds line 2"
;;
-q) exit;;
*) echo "I'm the fall thru default";;
esac
You can use the select builtin for this, which will let you use numbers for each option instead of letters, but will take care of reading and validating input:
select cmd in \
"List files of a directory" \
"Backup a file or directory" \
"Edit a user's password" \
"Exit";
do
case $cmd in
1) do_list_files ;;
2) do_backup_files ;;
3) do_edit_password ;;
4) exit 0 ;;
esac
done
You can change the prompt by setting the PS3 variable (e.g. PS3="Your choice? ")

Resources