LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-07-2009, 02:04 AM   #1
manwithaplan
Member
 
Registered: Nov 2008
Location: ~/
Distribution: Arch || Sidux
Posts: 393

Rep: Reputation: 45
New w/ dialog... implementing loop


I have several scripts that I am converting to dialog. Problem is that I am very new with dialog. I do have novice bash experience, and I have used zenity with some nautius scripts... I am major stumped with this dialog menu. This is just an test example of what I am trying to do. And I want one dialog menu to carry on to the next.

I am having a hard time with the last menu executing the specific command when selected from the list. I've tried while loops, 'if and else' Just stumped on how to store a "variable value" to use with my case statement.

Code:
#!/bin/bash

#USED TO TEST W/ Xdialog
DIALOG=${DIALOG=dialog}
 
$DIALOG --title "Proper tools needed for install" \
         --yesno "Certain tools are required for installation \
NANO, GEDIT, TOP and WGET 
Do you meet these requirments...?" 0 0
     case $? in
            0) clear;;
            1) exit;;
          255) exit;;
    esac 
#I HAVE TRIED A WHILE LOOP, IT ALWAYS RETURNS 0, I CAN NEVER EXECUTE 
#ANY COMMANDS WITHIN THE LIST OTHER THEN 0

$DIALOG --clear --title "TOOLS" \
        --menu "CHOOSE YOUR:" 20 51 4 \
        "1"  "NANO" \
        "2"  "GEDIT" \
        "3"  "TOP" 
 parti=$?
 case $parti in
       1) gparted;;
       2) gedit;;
       3) parted;;
     255) exit;;  
   esac
This code is incomplete. I'm just really confused on how I can implement a loop into this, and execute the command selected in the menu, then resume into another dialog box. The man pages aren't clear on what I should do. And I have searched google hi & low for an example. So I'm hoping someone out there has some good advice, and maybe know of any good sites that references dialog's with loops that executes commands. Would be very helpful.

Need to know how to bind the menu items with commands listed.

EDIT: It seems that the only values available are "0 , 1 , 255" in a case statement. I need to figure out how I can store a value of the list to launch the program.

Last edited by manwithaplan; 03-07-2009 at 04:05 AM.
 
Old 03-07-2009, 01:03 PM   #2
manwithaplan
Member
 
Registered: Nov 2008
Location: ~/
Distribution: Arch || Sidux
Posts: 393

Original Poster
Rep: Reputation: 45
It seems my approach was all wrong. After further research I found that the output of the dialog results in a stderr. So I needed to save the output into a tempfile, then trap, and uses case statements within another too be able to have multiple choices, by reading the tempfile output. After reading the tempfile output it matches with the internal case statement and executes the command... Very long winded.

I guess I was to tired to figure this out when I first posted


Code:
tempfile=`tempfile 2>/dev/null` || tempfile=/tmp/parti$$
trap "rm -f $tempfile" 0 1 2 5 15
$DIALOG --clear --title "TOOLS" \
        --menu "CHOOSE YOUR TOOL:" 20 51 4 \
        "1"  "nano" \
        "2"  "gedit" \
        "3"  "top" 2> $tempfile
retval=$?
choice=`cat $tempfile`
 case $retval in

  0)
    case $choice in
        "1") nano;;
        "2") gedit;;
        "3") top;;
  *)
      exit;;
   esac;;
  1)
      exit;;

255)
   exit;;
esac
rm -f /tmp/parti*
 
Old 03-07-2009, 08:05 PM   #3
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
You don't need a tempfile, you can capture the standard error of a command to a variable like this
Code:
choice=$(dialog arguments... 2>&1 1>/dev/null)
retval=$?
Also bash has arrays which can help make your a bit more concise:
Code:
CHOICES=([1]=nano gedit top)
command="${CHOICES[choice]}"
eval $command # using eval means $command can be any bash command, not just a program name
If you have an array of the form (1 nano 2 gedit 3 top) you can use it to pass arguments:
Code:
choice=$($DIALOG --clear --title "TOOLS" \
        --menu "CHOOSE YOUR TOOL:" 20 51 4 \
        "${CHOICES_ARGS[@]}" 2>&1)
Here is how to make (1 nano 2 gedit 3 top) from ([1]=nano gedit top):
Code:
CHOICES=([1]=nano gedit top)
declare -a CHOICES_ARGS # will be (1 nano 2 gedit 3 top)
{   # generate choices arguments to dialog                                                                                                                                                                          
    let j=0
    for i in "${!CHOICES[@]}" ; do
        args[$j]=$i
        let j+=1
        args[$j]="${CHOICES[i]}"
        let j+=1
    done
}
This way you can just change the CHOICES array when you want to add more tools.

Last edited by ntubski; 03-07-2009 at 08:16 PM. Reason: added quotes
 
Old 03-08-2009, 07:07 AM   #4
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,897

Rep: Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019
Quote:
Originally Posted by ntubski View Post
You don't need a tempfile, you can capture the standard error of a command to a variable like this
Code:
choice=$(dialog arguments... 2>&1 1>/dev/null)
retval=$?
That won't work with 'dialog' as it uses stdout to present the dialog to the users screen. You can work around it with something like...

Code:
exec 3>&1
choice=$(dialog --clear --title "TOOLS" --menu "CHOOSE YOUR TOOL:" 20 51 4 "1"  "nano" "2"  "gedit"  "3"  "top" 2>&1 1>&3)
I'm not sure if there's a neater way, I don't use dialog all that much.
 
Old 03-08-2009, 02:00 PM   #5
manwithaplan
Member
 
Registered: Nov 2008
Location: ~/
Distribution: Arch || Sidux
Posts: 393

Original Poster
Rep: Reputation: 45
Quote:
Originally Posted by GazL View Post
That won't work with 'dialog' as it uses stdout to present the dialog to the users screen. You can work around it with something like...
GazL, I figured that out yesterday when I was working with the /dev/null output. It wasnt working. Though I was able to get a variant to work with an input box, by outputing to tty.

Code:
TOOLS=$(dialog --backtitle "TOOLS SELECTION" --title "TOOLS" --inputbox "Enter whatever text" 12 40 2>&1 >/dev/tty)
GazL, your suggestion works perfectly for my menus... Thanks. Though could you explain to me these following commands? I'd rather learn to fish, then have someone fish for me.

"2>&1" Which I do know changes the stderr output...

"1>&3" Is this outputting to tty? and in the beginning you "exec 3>&1"
slightly confused on these suggestions.


thanks for all you input.

currently working on ntbuski's suggestions. New with working w/ array's, so I am looking to implement them into some of my code.

Are you suggesting declaring this array in the beginning of thee code?
Would love to know more about implementing this. I've been working off of online guides to learn... So forgive any ignorance.
 
Old 03-08-2009, 06:49 PM   #6
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Quote:
Originally Posted by Gazl
That won't work with 'dialog' as it uses stdout to present the dialog to the users screen.
Ah, good point, I was thinking that dialog put up some graphical thing.

I believe you can put all the redirection in one command like this:
Code:
choice=$(dialog arguments... 3>&2 2>&1 1>&3)
Quote:
Originally Posted by manwithaplan
I'd rather learn to fish, then have someone fish for me.
When you run a command like var=$(cmd) by default you have stdout (aka &1) goes to var, and stderr (aka &2) goes to screen, (as opposed to just running cmd which is both stdout and stderr go to screen). Each of the redirection commands run in order like so:
Code:
       | &1 (stdout) | &2 (stderr) | &3
-------+-------------+-------------+---------
       |  var        |  screen     |  closed
3>&2   |  var        |  screen     |  screen
2>&1   |  var        |  var        |  screen
1>&3   |  screen     |  var        |  screen

you could even add this for symmetry
3>&-   |  screen     |  var        |  closed
Quote:
"1>&3" Is this outputting to tty? and in the beginning you "exec 3>&1"
slightly confused on these suggestions.
When you do exec redirection the redirection stays in effect for the rest of the script instead of just a single command.
So "exec 3>&1" means point fd3 to wherever stdout points to, at the time of that command stdout is pointing to the screen (aka tty). Then the "1>&3" means point stdout to wherever fd3 points to, which is the screen because of the previous command.

Quote:
Are you suggesting declaring this array in the beginning of thee code?
Would love to know more about implementing this. I've been working off of online guides to learn... So forgive any ignorance.
Yes. I'm happy to answer questions but "more about implementing this" is a bit vague...

Last edited by ntubski; 03-08-2009 at 06:50 PM. Reason: quote attribution
 
Old 03-09-2009, 07:01 AM   #7
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,897

Rep: Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019
Quote:
Originally Posted by manwithaplan View Post
... Though I was able to get a variant to work with an input box, by outputing to tty.
Code:
TOOLS=$(dialog --backtitle "TOOLS SELECTION" --title "TOOLS" --inputbox "Enter whatever text" 12 40 2>&1 >/dev/tty)
Yes, 1>/dev/tty was the first thing I thought to try too. Interestingly, exec 3>/dev/tty also works just as exec 3>&1 did, however, using >/dev/tty directly inside the $() doesn't. I guess this is down to some internal nuance of how the shell handles command substitution, but I don't understand exactly what is going on here.

Quote:
Originally Posted by manwithaplan View Post
GazL, your suggestion works perfectly for my menus... Thanks. Though could you explain to me these following commands? I'd rather learn to fish, then have someone fish for me.
I'm exactly the same in that regard. I didn't mean to leave you hanging, but sometimes its hard to guess how much someone knows on a topic, and if folks are really interested they'll ask follow-ups.

Anyway, I see ntubski has answered your queries already so no need to go over it again.
 
Old 03-09-2009, 07:43 AM   #8
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,897

Rep: Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019
Quote:
Originally Posted by ntubski View Post
Ah, good point, I was thinking that dialog put up some graphical thing.

I believe you can put all the redirection in one command like this:
Code:
choice=$(dialog arguments... 3>&2 2>&1 1>&3)
Yep, that works nicely too, and saves the need to run the exec.


However, consider this...
Code:
./dialog_script >logfile.out 2>&1
Both of our suggestions would blow up if someone were to take this not uncommon action.


On reflection,
Code:
exec 3>/dev/tty  #  File Descriptor to tty for interaction with user
... somewhere near the top of your script and then, using
Code:
choice=$(dialog arguments... 2>&1 1>&3)
... seems to be be cleanest and clearest solution, and should work regardless of any manual redirection that is done when the script is called.

Was an interesting thread this, it's prompted me to figure out some things I hadn't considered before.
 
Old 03-09-2009, 01:46 PM   #9
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Quote:
Originally Posted by GazL View Post
However, consider this...
Code:
./dialog_script >logfile.out 2>&1
Both of our suggestions would blow up if someone were to take this not uncommon action.
Well I would say don't do that then What happens if you do
Code:
vim >logfile.out 2>&1
I guess it depends whether dialog_script is meant to work without user interaction. More of a design question really.

Quote:
however, using >/dev/tty directly inside the $() doesn't [work].
Not sure what you mean there, it seems to work for me, and I think manwithaplan was saying it worked for him.
 
Old 03-09-2009, 02:54 PM   #10
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,897

Rep: Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019
Quote:
Originally Posted by ntubski View Post
Not sure what you mean there, it seems to work for me, and I think manwithaplan was saying it worked for him.
Hmmm, yes it does for me today too, but didn't when I tried it yesterday. Maybe I'd managed to get the shell into a peculiar state or something. Oh well, not to worry.
 
Old 03-09-2009, 04:04 PM   #11
manwithaplan
Member
 
Registered: Nov 2008
Location: ~/
Distribution: Arch || Sidux
Posts: 393

Original Poster
Rep: Reputation: 45
Wow, a plethora of info. I'll post my example of trying to use dialog with a /dev/tty output.


Code:
ROOTS=$(dialog --backtitle "TEST - manwithaplan" --inputbox "Enter the device path for /ROOT \n\n\ Example:  /dev/sdx" 12 40 2>&1 >/dev/tty)
The thing is I am unable to use a case statement following this command. Meaning the output is a string of text e.g. "(/dev/sdx)". I have no idea how to position an "if" or a "case" after to read the string of text, then interpret for results like: e.g. (mount, mkdir, etc...). I am still fairly new with programming.

I'm also working on using dialog's --gauge to show output of wget, & tar extractions. I've been working on a grep command to "grep" wget's log file too show a percentage. I've seen some "sed" example's ... but I am still working on the use of syntax and, feel overwhelmed with using sed. I'm currently working on several different things... just confused. Any idea's? I've been working with this example here, but it doesnt seem to display the progress bar.

And the earlier post when I asked about implemtation, I guess I didnt understand ntbuski's post on adding an "arg". Like I said still grasping syntax and commands. So I was more or less asking for an example code, of implementing into my original example with a dialog menu. That way I can visualize it and interpret. Putting ntbuski's examples together. Just have hard time visualizing your suggestion.

Thanks guys for your explanations and examples. Very helpful.
 
Old 03-09-2009, 05:09 PM   #12
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,897

Rep: Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019
Quote:
Originally Posted by manwithaplan View Post
Code:
ROOTS=$(dialog --backtitle "TEST - manwithaplan" --inputbox "Enter the device path for /ROOT \n\n\ Example:  /dev/sdx" 12 40 2>&1 >/dev/tty)
The thing is I am unable to use a case statement following this command.

I'll just do something silly below as an example to give you and idea how it all hangs together and get you started...

Code:
#!/bin/bash

ROOTS=$(dialog --backtitle "TEST - manwithaplan" --inputbox "Enter the device path for /ROOT \n\n\ Example:  /dev/sdx" 12 40 2>&1 >/dev/tty)

dialog_rc=$?

if [ $dialog_rc = 0 ] ; then 

  case "$ROOTS" in
    (/dev/apple)      echo "Apples are fruity"
                      ;;
    (/dev/banana)     echo "Bananas are fruity..."
                      echo "... and curvy."
                      ;;
    (/dev/orange)     echo "Oranges are, well... Orange"
                      ;;
    (*)               echo "Everything else is a strange fruit"
  esac

else
  echo "You selected <cancel>"
fi
If you google for 'shell scripting tutorial' you'll find quite a bit of good information out there to help you along.

have fun.
 
Old 03-10-2009, 02:03 AM   #13
gnashley
Amigo developer
 
Registered: Dec 2003
Location: Germany
Distribution: Slackware
Posts: 4,928

Rep: Reputation: 612Reputation: 612Reputation: 612Reputation: 612Reputation: 612Reputation: 612
You might try using the '--stdout' option.
 
Old 03-10-2009, 02:20 AM   #14
manwithaplan
Member
 
Registered: Nov 2008
Location: ~/
Distribution: Arch || Sidux
Posts: 393

Original Poster
Rep: Reputation: 45
Actually I used a wildcard in a case statement. " /dev/*) " Seemed to work. I also put it in a while loop to return to the input box if the incorrect data was imputed. In case of user error or typo's.

GazL's e.g. was too limited. I just needed to experiment with using "*" wildcards in case statements to see if it would work... And to my surprise it worked.

Last edited by manwithaplan; 03-10-2009 at 02:23 AM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
how to loop over text file lines within bash script for loop? johnpaulodonnell Linux - Newbie 9 07-28-2015 03:49 PM
bash loop within a loop for mysql ops br8kwall Programming 10 04-30-2008 03:50 AM
converting shell while loop to for loop farkus888 Programming 8 09-12-2007 02:30 AM
Bash Loop Dialog xlordt Programming 5 09-26-2006 09:40 AM
Implementing a blocking loop (Java or C) Miaire Programming 4 04-28-2005 02:22 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 08:25 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration