The link below:
https://serverfault.com/questions/144939
It correctly shows how to create a menu using the "dialog" command but does not show how to create the "select all" shortcut button.
How to create the "Select all" button?
Like this:
#!/bin/bash
onoff=off # all unset by defaul
dialog1(){ dialog --output-fd 1 --extra-button --extra-label "Select All" --checklist "Select options:" 0 0 0 "$#"; }
dialog2(){ choices=$(dialog1 "${options[#]}"); }
set_options(){ # make options array dynamic
options=(
1 "Option 1" $onoff
2 "Option 2" $onoff
3 "Option 3" $onoff
4 "Option 4" $onoff
)
}
set_option
dialog2
case $? in # if 'Select All' presssed
3) onoff=on # set all to on
set_options # reassemble options
dialog2;; # and run dialog again
esac
clear
echo $choices
Ivan, thank you.
Taking a cue from your solution, merging it with that of the link:
https://serverfault.com/questions/144939
and improving the code in my own way, I got this solution:
#!/bin/bash
onoff=off
cmd=(dialog --output-fd 1 --separate-output --extra-button --extra-label "Select All" --cancel-label "Select None" --checklist "Select options:" 0 0 0)
load-dialog () {
options=(
1 "Option 1" $onoff
2 "Option 2" $onoff
3 "Option 3" $onoff
4 "Option 4" $onoff
)
choices=$("${cmd[#]}" "${options[#]}")
}
load-dialog
exit_code="$?"
while [[ $exit_code -ne 0 ]]; do
case $exit_code in
1) clear; onoff=off; load-dialog;;
3) clear; onoff=on; load-dialog;;
esac
exit_code="$?"
done
clear
for choice in $choices
do
case $choice in
1) echo "First Option";;
2) echo "Second Option";;
3) echo "Third Option";;
4) echo "Fourth Option";;
esac
done
sleep infinity
Related
I just started to learn bash and create a GUI with Dialog, but I'm having a problem with my program, any help will be appreciate it. Thanks
I want to create a program which will display a dialog which will ls only directories from the current folder:
display_folders()
{
while true; do
let count=0 #define counting variable
w=() #define working array
while read -r line; do #process file by file
let count=$count+1
w+=("$line" "$line")
done < <(ls -d */)
file=$(dialog --title "List directory" --cancel-label "Exit" --no-tags --menu "Please choose one folder: " 10 40 0 "${w[#]}" 3>&2>
#clear
exit_status=$?
echo $exit_status
case $exit_status in
1) echo "Program terminated"
exit ;;
255) echo "Program aborted"
exit 1 ;;
esac
echo "this is $file"
case "$file" in
*)
cd $file
display_result "$file" ;;
esac
done
}
After selecting the specified dir (for example ANIMALS) I want to cd into it and make some actions (the code is just for the 1 selection)
display_result()
{
while true; do
selection=$(dialog --title "folder" \
--cancel-label "Exit" \
--menu "Choose an action: " 10 40 0 \
"1" "List details about files" \
"2" "Search for word" \
"3" "Generate CSV" \
"4" "More info CSV" \
"5" "Search file" \
3>&2 2>&1 1>&3)
exit_status=$?
case $exit_status in
1) break ;;
255) echo "Program aborted"
exit 1 ;;
esac
case $selection in
1 )
result=$(ls -lt)
display_file_details ;;
esac
done
}
display_file_details()
{
dialog --title "file details" --no-collapse --msgbox "$result" 0 0
}
The problem is, in the selected folder (ANIMALS) I have another folder too (for example OTHERS), when I am ls all from the folder ANIMALS it will display me everything (which is good), but after I exit from the display --msgbox will display me another --menu only with OTHERS folder, and the display_result for it, if I exit from this too, the program will exit with 1 code.
What I want is to cd into ANIMALS, which is the dir from current folder, then list the options (1,2,3,4,5), and after exit from the options display I want to take me back to my current folder with ANIMALS in it.
You don't need this 'while true; do' loops. Create first dialog:
dialog1(){
list=( */ )
folder=$( dialog --title "List directory" --cancel-label "Exit" \
--no-items --menu "Please choose one folder: " \
--output-fd 1 10 40 0 ${list[#]///} )
echo $folder
dialog2
}
And the second like this:
dialog2(){
# another dialog here
# some code here
dialog1 # run first dialog again
}
And start first dialog:
dialog1
p.s. check out my projects sshto and kube-dialog created via dialog.
Thank's #Ivan but this is not what I wanted.
I solved it by going back with a dir in the same case :
display_file_details()
{
dialog --title "file details" --no-collapse --msgbox "$1" 0 0
}
dialog1(){
list=( */ )
folder=$( dialog --title "List directory" --cancel-label "Exit" \
--no-items --menu "Please choose one folder: " \
--output-fd 1 10 40 0 ${list[#]///} )
exit_status=$?
echo "$exit_status dialog1"
case $exit_status in
1 | 255)
return 0
;;
*)
diag2_return=255
while [ "$diag2_return" -ne "0" ]; do
dialog2 $folder
diag2_return=$?
done
esac
return 1
}
dialog2(){
echo "hereeeeeeeeee $1"
selection=$(dialog --title "folder" --cancel-label "Exit" \
--menu "Choose an action: " --output-fd 1 10 40 0 \
"1" "List details about files" \
"2" "Search for word" \
"3" "Generate CSV" \
"4" "More info CSV" \
"5" "Search file" )
exit_status=$?
echo "$exit_status dialog2"
case $exit_status in
1 | 255)
return 0
;;
esac
case $selection in
1 )
cd "$1"
result=$(ls -lt)
display_file_details "$result"
cd ..
;;
esac
return 1
}
diag_return=255
while [ "$diag_return" -ne "0" ]; do
dialog1
diag_return=$?
done
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
#!/bin/bash
function advancedMenu() {
ADVSEL=$(whiptail --title "Advanced Menu" --fb --menu "Choose an option" 15 60 4 \
"1" "Delete group" \
"2" "Create login name" \
"3" "Exit" 3>&1 1>&2 2>&3)
case "$ADVSEL" in
1)
echo "Option 1"
whiptail --title "Option 1" --msgbox "You chose group deleting. Exit status $?" 8 45
bash ./script3;;
2)
echo "Option 2"
whiptail --title "Option 1" --msgbox "You chose login name creating. Exit status $?" 8 45
bash ./script;;
3)
echo "Option 3"
whiptail --title "Option 1" --msgbox "You chose exit. Exit status $?" 8 45
;;
esac
}
advancedMenu
I don't know how to loop my case statement. I have user friendly interface here. Someone chooses 1\2 or exit. 1 and 2 runs another scripts. So when 1 is clicked and scripted is finished, I need the main menu back until case 3 is clicked. I will be grateful for your help!
#!/bin/bash
export NEWT_COLORS='
window=white,blue
border=white,green
textbox=white,green
button=black,white
'
{
for ((i = 0 ; i <= 100 ; i += 1)); do
sleep 1
echo $i
done
} | whiptail --gauge "Wait..." 6 60 0
touch 35_2.csv
while read line; do
IFS=","
set -- $line
group_name=$1
student_name=$2
student_name=`echo $student_name | tr -d '\r\n' `
login_name=`echo $student_name | sed 's/[b\`]//g;'`
login_name=`echo $login_name | sed 'y/абвгдеєзиіїйклмнопрстуфхь/abvgdeeziiijklmnoprstufh_/'`
login_name=`echo $login_name | sed 's/ /_/g; s/С†/ts/g; s/Р¶/zh/g; s/С‡/ch/g; s/С€/sh/g; s/С‰/sh/g; s/СЋ/yu/g; s/СЏ/ya/;'`
echo "$group_name, $student_name, $login_name" >> 35_2.csv
done < 35_2.csv
Don't look at wrong encoding. Your decision seemed to be right. The first script runs then menu goes back. However, when I start the second script the menu does not go back. Attached the 2nd's script code.
Simply put a while loop around it.
#!/bin/bash
function advancedMenu() {
while :; do
ADVSEL=$(whiptail --title "Advanced Menu" --fb --menu "Choose an option" 15 60 4 \
"1" "Delete group" \
"2" "Create login name" \
"3" "Exit" 3>&1 1>&2 2>&3)
case "$ADVSEL" in
1)
echo "Option 1"
whiptail --title "Option 1" --msgbox "You chose group deleting. Exit status $?" 8 45
bash ./script3;;
2)
echo "Option 2"
whiptail --title "Option 1" --msgbox "You chose login name creating. Exit status $?" 8 45
bash ./script;;
3)
echo "Option 3"
whiptail --title "Option 1" --msgbox "You chose exit. Exit status $?" 8 45
return
;;
esac
done
}
advancedMenu
I'm not sure what you expect Exit status $? to show. $? is the exit status of the echo statement on the previous line, so it will almost always just be 0.
I am creating my own bash script, but when I get out the second menu, the code don't let me enter into the second menu again.
The only way I had to explain this bug is that when I put 6 to go back to the first while the read fixes the 6 what causes confusion with the problem?
But that does not make sense because if it fixed the 6 would do echo " <--- back"
Can someone tell me why?
while [ "$myscript" != "6" ]
do
echo "Script Menu"
echo " 1 - Open"
echo " 2 - Download"
echo " 3 - Update && Upgrade"
echo " 6 - Exit"
echo "Choose Your Script: "
read myscript
case $myscript in
1)
while [ "$open" != "6" ]
do
clear
echo "Open Menu"
echo " 1 - Rythombox"
echo " 2 - Anaconda"
echo " 3 - VSCode"
echo " 4 - Terminal"
echo " 6 - <-----Back"
echo "Choose Your Open: "
read open
case $open in
1)
echo " Opening Rhythmbox"
gnome-terminal --tab -- "rhythmbox"
;;
6)
echo "<--- Back"
;;
*)
echo "Not a option!"
;;
esac
done
The problem, as Gordon Davisson noticed, is indeed that $open is still "6" from the last time.
The solution is simply to bring reading and comparing the input choice in a sane order, not testing [ "$open" != "6" ] before the variable has been read in:
while echo "Script Menu"
echo " 1 - Open"
echo " 2 - Download"
echo " 3 - Update && Upgrade"
echo " 6 - Exit"
echo "Choose Your Script: "
read myscript
[ "$myscript" != "6" ]
do
case $myscript in
1) while clear
echo "Open Menu"
echo " 1 - Rythombox"
echo " 2 - Anaconda"
echo " 3 - VSCode"
echo " 4 - Terminal"
echo " 6 - <-----Back"
echo "Choose Your Open: "
read open
[ "$open" != "6" ]
do
case $open in
1) echo " Opening Rhythmbox"
gnome-terminal --tab -- "rhythmbox"
;;
6) echo "<--- Back"
;;
*) echo "Not a option!"
;;
esac
done
esac
done
I have an options menu function:
function()
{
echo "1 Option 1"
echo "2 Option 2"
echo "3 Option 3"
echo "q Exit"
read -p "Select 1-3 ή \"q\" to quit: " i
case "$i" in
1)
echo "option 1"
echo;;
2)
echo "option 2"
echo;;
3)
echo "option 3"
echo;;
q) echo -e "\033[01;33mexit!!!\033[39m"
sleep 1
clear
exit ;;
*)
echo "Unknown command"
read -s -n 1 -p "Press any key to continue…"
echo
esac
}
while:
do function
done
The above works fine, but need to press enter after I input the number before the command run. Is there any way to immediately run the command when I press the key?
You've got the answer right in your sample code (in the second read). You want to take advantage of bash's read -n 1 capability (note, this is not POSIX compliant, so it won't reliably work in /bin/sh unless that happens to map to bash):
read -n 1 -p "Select 1-3 ή \"q\" to quit: " i