Bash Input Variables & Loop - bash

My script
#!/bin/bash
while :
do
echo "[*] 1 - Create a gnome-terminal"
echo "[*] 2 - Display Ifconfig"
echo -n "Pick an Option > "
read Input
if [ "$Input" = "1" ]; then
gnome-terminal
sleep 3
echo "[*] 1 - Create a gnome-terminal"
echo "[*] 2 - Display Ifconfig"
echo -n "Pick an Option > "
read Input
fi
if [ "$Input" = "2" ]; then
clear
ifconfig
echo "[*] 1 - Create a gnome-terminal"
echo "[*] 2 - Display Ifconfig"
echo -n "Pick an Option > "
read Input
fi
done
Doesn't reuse the Input variable, say if you want to run the ifconfig option multiple times in a row. It rechecks the first variable string to see if it matches "1", and when it doesn't it echoes back the list of options. Any ideas on how to make any input variable accessible regardless of when it is used?

The problem is that you're writing out the menu twice on each iteration. Stop doing that:
#!/bin/bash
while :
do
echo "[*] 1 - Create a gnome-terminal"
echo "[*] 2 - Display Ifconfig"
echo -n "Pick an Option > "
read Input
if [ "$Input" = "1" ]; then
gnome-terminal
sleep 3
fi
if [ "$Input" = "2" ]; then
clear
ifconfig
fi
done

Use select instead of rolling your own menu:
choices=(
"Create a gnome-terminal"
"Display Ifconfig"
)
PS3="Pick an Option > "
select action in "${choices[#]}"; do
case $action in
"${choices[0]}") gnome-terminal; sleep 3;;
"${choices[1]}") clear; ifconfig;;
*) echo invalid selection ;;
esac
done
select gives you an infinite loop by default. If you want to break out of it, put a break statement into the case branch.

Related

Pass prompt option to a file

I want to create a script where I have pre-defined option values.
opt1 opt2 opt3
I will start a script and it will ask me to choose from opt1 - opt3.
Once I pick e.g. opt2, that opt2 will then be passed as a variable.
How can I please achieve it?
You can use the "case" command to check if the user value is on a list of expected values:
#!/bin/bash
selected_option=""
echo " *** MENU ***"
echo "1) Opt1"
echo "2) Opt2"
echo "3) Opt3"
echo -n " Please, enter your option: "
read user_answer
case $user_answer in
1|2|3) selected_option="$user_answer"
;;
*) echo "Invalid Option!"
esac
##### Show the result only if the user selected an valid option #####
if [[ ! -z "${selected_option}" ]]; then
echo "Selected Option: [${selected_option}]"
fi
The '|' can be used to separate the valid options, and it will act as an "or" operator.
The '*' section will be executed if the previous condition is not satisfied, which means a "default" behavior, at this case it will display "Invalid Option" message.
Finally, the last if checks if the variable "${selected_option}" is empty, if not it is printed, but you can do whatever you want with that.
#!/bin/sh
echo "choose an option [ 1 opt1 | 2 opt2 | 3 opt3 ]"
read input
if [ $input == 1 ]
then
output="option 1 was chosen"
elif [ $input == 2 ]
then
output="option 2 was chosen"
elif [ $input == 3 ]
then
output="option 3 was chosen"
else
output="invalid input"
fi
echo "$output"

How can we get back in the right place (that we specify) after signal?

I have made my own signal handler, but I need to get back before
# I NEED TO JUMP HERE
echo -e "Input name of the file"
read filename
so I could input filename several times. But when I execute signal (Ctrl + C), I go into handler and then in the place where I execute signal (so I can input filename only once).
Is there any command (like siglongjump and setlongjump in C), that help me control the whole process.
count=0
flag=0
handl(){
echo
if test $flag -eq 0
then echo "You did not input filename"
fi
file $filename | grep "C source" > /dev/null
a=$?
if test $a -eq 0
then
count=$((count+1))
fi
echo "Number of C source files: $count"
}
trap handl 2
echo -e "Input name of the file"
read filename
flag=1
sleep 1
You can modularize your script and only print a prompt in the signal
handler:
#!/usr/bin/env bash
count=0
flag=0
handl(){
echo
if test $flag -eq 0
then echo "You did not input filename"
prompt
return
fi
file "$filename" | grep "C source" > /dev/null
a=$?
if test $a -eq 0
then
count=$((count+1))
fi
echo "Number of C source files: $count"
}
prompt(){
echo -e "Input name of the file"
}
input(){
read -r filename
flag=1
echo sleep 1
sleep 1
}
trap handl 2
while true
do
prompt
input
done

Return to previous commands in bash script?

I'm trying to implement a prev option in my bash script to go back to the previous "menu", as well as a way for the script to ask for user input again if no variable is set for $name.
Heres my bash script:
#!/bin/bash
#Menu() {
for (( ; ; ))
do
beginORload=
echo "Choose option:"
echo "1 - Begin"
echo "2 - Load"
read -p "?" beginORload
#}
#Begin() {
if [ "$beginORload" -eq "1" ]
then
clear
for (( ; ; ))
do
echo "Beginning. What is your name?"
read -p "?" name
#If "prev" specified, go back to #Menu()
if [ "$name" -eq "prev" ]
then
Menu
fi
#If nothing specified, return to name input
if [ -z ${name+x} ]
then
Begin
else
break
fi
echo "Hi $name !"
done
fi
done
In batch, I could simply do:
:menu
echo Choose option:
echo 1 - Begin
echo 2 - Load
[...]
:begin
[...]
if "%name%==prev" goto menu
if "%name%==" goto begin
the issue is I keep running into errors all over the place, and I can't figure out what to type to get it to work
im running Yosemite btw. Thankyou
Something like this is close to what you expect:
while [[ $answer -ne '3' ]];do
echo "Choose option:"
echo "1 - Begin"
echo "2 - Load"
echo "3 - Exit"
read -p "Enter Answer [1-2-3]:" answer
case "$answer" in
1) while [[ "$nm" == '' ]];do read -p "What is your Name:" nm;done # Keep asking for a name if the name is empty == ''
if [[ $nm == "prev" ]];then nm=""; else echo "Hello $nm" && break; fi # break command breaks the while wrapper loop
;;
2) echo 'Load' ;;
3) echo 'exiting...' ;; # Number 3 causes while to quit.
*) echo "invalid selection - try again";; # Selection out of 1-2-3 , menu reloaded
esac # case closing
done # while closing
echo "Bye Bye!"
As a general idea you can wrap up your case selection in a while loop which will break under certain circumstances (i.e If Option 3 is selected or if a valid name is given (not blank - not prev)
PS1: In bash you compare integers with -eq , -ne, etc but you compare strings with == or !=
PS2: Check the above code online here

Bash while command

I have created a bash menu script, using options 1-8. For my second menu option I am using the while command to display the current time and date. However, when I press Ctrl+C to end the display of the date it jumps out of the entire script rather than redisplay the menu. Is there a way around this?
yeah, make functions
#more code here ...
display_main_menu() {
while true; do
echo -e "Please select an action:"
echo -e " "
echo -e "1 - Transfer a local file to all servers."
echo -e "2 - Execute a command(s) on all servers."
echo -e "9 - Display all servers."
echo -e "0 - Exit"
echo ""
read -p "" action
case $action in
"1" ) function_to_transfer_file ;;
"2" ) function_to_execute_command ;;
"9" ) function_to_show_server;;
"0" ) exit;;
* ) echo "Please select a valid action.";;
esac
done
}
#more code here ...
Make multiple functions, one for each option in primary menu. Here option 0 exits the script completely.
For secondary menu functions ... option 0 should execute function display_main_menu
You want catch the signal SIGINT (Ctrl+C) and break
trap 'break' SIGINT
For example:
#!/bin/bash
trap 'break' SIGINT
while :
do
sleep 1
echo "foo"
done
echo "bar"
Take a look here to have more details:
http://tldp.org/LDP/Bash-Beginners-Guide/html/chap_12.html
#!/bin/bash
#more code here ...
display_main_menu() {
while true; do
echo -e "Please select an action:"
echo -e " "
echo -e "1 - display time"
echo -e "2 - Execute a command(s) on all servers."
echo -e "9 - Display all servers."
echo -e "0 - Exit"
echo ""
read -p "" action
case $action in
"1" ) trap 'break' SIGINT; while true; do echo "$(date '+%D %T' )"; sleep 1; done ;;
"2" ) function_to_execute_command ;;
"9" ) function_to_show_server;;
"0" ) exit;;
* ) echo "Please select a valid action.";;
esac
done
}
display_main_menu

Preventing a shell script from exiting with Control C

so I am trying to create a script which gives the user some options to do things, one of that option is to exit the script. However, I want to prevent the user from exiting the script using Control c so that the only way to exit is to select the right option. Is it possible to make the script so that when the user hits control c, the program will not exit, but rather it would echo something like "enter 0 to exit"?
#!/bin/bash
# Acts as a simple administration menu
OPTION=0
echo "-----------------Admin Menu-------------------"
echo "Please select one of the following options: "
echo ""
echo "1 - Run top."
echo "2 - Show system uptime."
echo "3 - Show logged in users."
echo "4 - Exit Menu."
echo "5 - Reprint this menu."
echo "----------------------------------------------"
echo "Please choose an option (5 to reprint menu):"
read OPTION
while [ "$OPTION" -ne 4 ]
do
if [ "$OPTION" -eq 1 ]; then
clear
top -n1
elif [ "$OPTION" -eq 2 ]; then
clear
uptime
elif [ "$OPTION" -eq 3 ]; then
clear
who
elif [ "$OPTION" -eq 4 ]; then
clear
OPTION=4
elif [ "$OPTION" -eq 5 ]; then
clear
echo "------------COSC 2306 Admin Menu--------------"
echo "Please select one of the following options: "
echo ""
echo "1 - Run top."
echo "2 - Show system uptime."
echo "3 - Show logged in users."
echo "4 - Exit Menu."
echo "5 - Reprint this menu."
echo "----------------------------------------------"
else
clear
echo "ERROR: Incorrect Input."
fi
echo "Please choose an option (5 to reprint menu):"
read OPTION
done
clear
You can use the trap built-in to catch SIGINT ( ctrl + C generates the signal SIGINT) and print your message:
trap 'echo "enter 0 to exit"' SIGINT
Similarly you can catch other signals too. To get the list of signals use kill -l.

Resources