Select case menu not working - bash

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

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

getopts not iterating on shell script

I'm experiencing an issue with a getopts on a bash script. In particular the code below seems not to work with more than 1 parameter.
If I do:
./script.sh - t template-name -m terminal-name
only template variable is populated while if i do
./script.sh - m terminal-name -t template-name
only terminal is pupulated
while getopts ":m:t:r:" optname;
do
case "${optname}" in
"m")
terminal = $OPTARG
;;
"t")
echo "Using template: $OPTARG"
template = "$(cat $OPTARG)"
;;
"r")
reboot="yes"
tput setaf 1; echo "TERMINAL WILL BE REBOOTED WHEN DONE!!"
;;
"?")
echo "Unknown option $OPTARG"
;;
":")
echo "No argument value for option $OPTARG"
;;
*)
# Should not occur
echo "Unknown error while processing options"
;;
esac
done
shift $((OPTIND-1))
I believe that if you are using getopts in a while you do not need the shift.

Check for invalid input in a menu

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.

Avoid options to be taken as argument automatically

I'd like to do some error checking for a bash script I am writing. In particular, I wish to ensure the following option not to be considered as the argument of an option (intentionally) left empty.
Let's say the following snippet
while getopts “hhelpc1:2:” OPTION
do
case "$OPTION" in
h|help)
usage
exit 1
;;
1)
var1=${OPTARG}
;;
2)
var2=${OPTARG}
;;
c)
test1
;;
esac
done
Assuming my script is called test.sh
By doing something like
./test.sh -1 -2 dddd -c
In the above circumstance test1 output an error message that -2 option is empty. On the opposite, I'd like to raise a warning for -1 being empty, whereas at present -2 will be taken as the argument for -1.
Any help?
Thanks
Andrea
getopts:
only handles short option names, so you cannot put "help" in your option string -- that means you're looking for "-h", "-e", "-l", "-p"
cannot look for missing arguments the way you're hoping. You'll have to examine $OPTARG to check if it looks like one of your options.
Add a leading : to the opt string to handle getopts errors yourself.
Here's a reworking of your code and I'm sure there are plenty of cases I'm not catching
#!/bin/bash
usage () { echo usage ...; }
test1 () { echo test1; }
shopt -s extglob
while getopts ":hc1:2:" opt
do
case $opt in
h)
usage
exit 1
;;
1)
case $OPTARG in
-[hc2]*)
echo "error: required argument missing for -1"
usage
exit 1
;;
*) var1=$OPTARG
;;
esac
;;
2)
case $OPTARG in
-[hc1]*)
echo "error: required argument missing for -2"
usage
exit 1
;;
*) var2=$OPTARG
;;
esac
;;
c)
test1
;;
:)
echo "error: required argument missing for -$OPTARG"
usage
exit 1
;;
\?)
# unknown argument, handle accordingly
;;
esac
done
shift $((OPTIND - 1))
echo "var1=$var1"
echo "var2=$var2"
echo "rest=$*"
Update 2014-01-23
Here's one technique:
do_test1=false
while getopts ...
case $opt in
...
c) do_test1=true ;;
...
esac
done
shift $((OPTIND - 1))
# execute function "test1" if "-c" was given:
$do_test1 && test1

Resources