Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BASH scripts : whiptail file select

I've found a great little program that will allow me to add user friendly GUI's to my Bash Scripts;

whiptail

However the whiptail man page isn't all that helpful and doesn't provide any examples. After doing some google searches I understand how to create a simple yes/no menu using whiptail:

#! /bin/bash
# http://archives.seul.org/seul/project/Feb-1998/msg00069.html
if (whiptail --title "PPP Configuration" --backtitle "Welcome to SEUL" --yesno "
Do you want to configure your PPP connection?"  10 40 )
then 
        echo -e "\nWell, you better get busy!\n"
elif    (whiptail --title "PPP Configuration" --backtitle "Welcome to
SEUL" --yesno "           Are you sure?" 7 40)
        then
                echo -e "\nGood, because I can't do that yet!\n"
        else
                echo -e "\nToo bad, I can't do that yet\n"
fi

But what I would really like to build a file select menu using whiptail to replace some old code I have in a few different backup/restore bash scripts I have:

#!/bin/bash
#This script allows you to select a file ending in the .tgz extension (in the current directory)
echo "Please Select the RESTORE FILE you would like to restore: "
   select RESTOREFILE in *.tgz; do
   break #Nothing
   done
echo "The Restore File you selected was: ${RESTOREFILE}"

I assume this has to be done via the '--menu' option of whiptail, but I am not sure how to go about it? Any pointers? Or can you point me in the direction of some whiptail examples?

like image 377
BassKozz Avatar asked Oct 13 '09 20:10

BassKozz


2 Answers

Build an array of file names and menu select tags:

i=0
s=65    # decimal ASCII "A" 
for f in *.tgz
do
    # convert to octal then ASCII character for selection tag
    files[i]=$(echo -en "\0$(( $s / 64 * 100 + $s % 64 / 8 * 10 + $s % 8 ))")
    files[i+1]="$f"    # save file name
    ((i+=2))
    ((s++))
done

A method like this will work even if there are filenames with spaces. If the number of files is large, you may have to devise another tag strategy.

Using alpha characters for the tags lets you press a letter to jump to the item. Numeric tags don't seem to do that. If you don't need that behavior, then you can eliminate some complexity.

Display the menu:

whiptail --backtitle "Welcome to SEUL" --title "Restore Files" \
    --menu "Please select the file to restore" 14 40 6 "${files[@]}"

If the exit code is 255, the dialog was canceled.

if [[ $? == 255 ]]
then
    do cancel stuff
fi

To catch the selection in a variable, use this structure (substitute your whiptail command for "whiptail-command"):

result=$(whiptail-command 2>&1 >/dev/tty)

Or

result=$(whiptail-command 3>&2 2>&1 1>&3-)

The variable $result will contain a letter of the alphabet that corresponds to a file in the array. Unfortunately, Bash prior to version 4 doesn't support associative arrays. You can calculate the index into the array of the file from the letter like this (notice the "extra" single quote):

((index = 2 * ( $( printf "%d" "'$result" ) - 65 ) + 1 ))

Example:

Welcome to SEUL
                ┌──────────┤ Restore Files ├───────────┐
                │ Please select the file to restore    │
                │                                      │
                │            A one.tgz      ↑          │
                │            B two.tgz      ▮          │
                │            C three.tgz    ▒          │
                │            D another.tgz  ▒          │
                │            E more.tgz     ▒          │
                │            F sp ac es.tgz ↓          │
                │                                      │
                │                                      │
                │       <Ok>           <Cancel>        │
                │                                      │
                └──────────────────────────────────────┘
like image 153
Dennis Williamson Avatar answered Sep 18 '22 13:09

Dennis Williamson


Whiptail is a lightweight reimplementation of the most popular features of dialog, using the Newt library. I did a quick check, and many features in Whiptail seem to behave like their counterparts in dialog. So, a dialog tutorial should get you started. You can find one here but Google is your friend of course. On the other hand, the extended example probably contains a lot of inspiration for your problem.

like image 32
fvu Avatar answered Sep 21 '22 13:09

fvu