2009-10-13 8 views
6

J'ai trouvé un super petit programme qui me permettra d'ajouter des GUI conviviaux à mes scripts Bash;Scripts BASH: fichier whiptail select

whiptail

Cependant, le whiptail man page est pas du tout utile et ne fournit pas d'exemples. Après avoir fait quelques recherches sur Google, je comprends comment créer un simple oui/non menu à l'aide 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 

Mais ce que je voudrais vraiment construire un fichier menu de sélection à l'aide whiptail pour remplacer un vieux code que j'ai dans quelques différents de sauvegarde/restauration des scripts bash j'ai:

#!/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}" 

Je suppose que cela doit être fait via l'option « --menu » de whiptail, mais je ne suis pas sûr de savoir comment s'y prendre? Des pointeurs? Ou pouvez-vous me montrer des exemples de whiptails?

+0

J'ai apporté une petite modification à ma réponse (la formule de conversion octale). –

Répondre

8

Construire un tableau de noms de fichiers et balises select du menu:

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 

Une méthode comme cela fonctionnera même s'il y a des noms de fichiers avec des espaces. Si le nombre de fichiers est important, vous devrez peut-être concevoir une autre stratégie de tag. L'utilisation des caractères alphabétiques pour les étiquettes vous permet d'appuyer sur une lettre pour accéder directement à l'élément. Les balises numériques ne semblent pas le faire. Si vous n'avez pas besoin de ce comportement, vous pouvez éliminer une certaine complexité.

Afficher le menu:

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

Si le code de sortie est de 255, la boîte de dialogue a été annulée.

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

Pour attraper la sélection dans une variable, utilisez cette structure (remplacez votre commande whiptail pour "whiptail-commande"):

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

Ou

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

La $result variable contenir une lettre de l'alphabet qui correspond à un fichier dans le tableau. Malheureusement, Bash avant la version 4 ne supporte pas les tableaux associatifs. Vous pouvez calculer l'index dans le tableau du fichier de la lettre comme celui-ci (notez la citation unique « supplémentaire »):

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

Exemple:

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>  │ 
       │          │ 
       └──────────────────────────────────────┘ 
+0

S'il vous plaît noter: J'ai modifié ma réponse pour remplacer la formule de conversion octale précédente qui était ( presque) complètement faux. –

+0

Pour les fichiers temporaires, vous pouvez utiliser mktemp. Par exemple, mytempfile=$(mktemp) ; echo "Hello world">$mytempfile; echo Contents of ${mytempfile}: $(cat $mytempfile) ; rm -f $mytempfile jbatista

+0

@jbatista: C'est vrai, mais comment est-ce applicable? Il n'y a aucune mention de fichiers temporaires ici. –

3

Whiptail est une réimplémentation légère des caractéristiques les plus populaires de dialog, en utilisant le Newt library. J'ai fait une vérification rapide, et de nombreuses fonctionnalités dans Whiptail semblent se comporter comme leurs homologues dans le dialogue. Ainsi, un tutoriel de dialogue devrait vous aider à démarrer. Vous pouvez en trouver un here mais Google est votre ami bien sûr. D'autre part, le extended example contient probablement beaucoup d'inspiration pour votre problème.

0

J'ai essayé la suite, ce qui a fonctionné:

whiptail --title "PPP Config" --backtitle "Welcome to SEUL" --menu YourTitle 20 80 10 `for x in $(ls -1 *.tgz); do echo $x "-"; done` 

vous pouvez changer cela en un multiple-liner ainsi, j'ai ajouté la vérification de la liste vide:

MYLIST=`for x in $(ls -1 *.tgz); do echo $x "-"; done` 
WC=`echo $MYLIST | wc -l` 

if [[WC -ne 0]]; then 
    whiptail --title "PPP Config" --backtitle "Welcome to SEUL" --menu YourTitle 20 80 10 $MYLIST 
fi 

dont vous avez besoin pour ajuster les nombres afin d'obtenir une interface propre. Et vous pouvez remplacer le "-" par n'importe quoi d'autre si vous voulez. Mais si vous ne le faites pas, vous verrez 2 entrées par ligne. A propos: L'entrée sélectionnée est imprimée sur stderr.

Cela pourrait avoir besoin de plus d'amélioration, mais pour une idée de base, je pense que c'est suffisant.

0

Cela semble être l'un des meilleurs résultats lorsque vous recherchez whiptail, et aucun des résultats précédents a fonctionné pour moi. C'est ce que j'ai fini par utiliser:

#! /bin/bash 
shopt -s nullglob 
dir=`pwd` 
cd /path/to/files 
arr=(*.tgz) 
for ((i=0; i<${#arr[@]}; i++)); do j=$((2*$i+2)); a[j]="${arr[$i]}"; a[j+1]=""; done 
a[0]="" 
# Next line has extra spaces at right to try to center it: 
a[1]="Please make a selection from the files below              " 
result=$(whiptail --ok-button "OK button text" --cancel-button "Cancel Button Text" --title "Title Text" --backtitle "Text at upper left corner of page" --menu "Menu Text (not used??)" 30 160 24 "${a[@]}" 2>&1 >/dev/tty) 
if [[ $? = 0 ]] 
then 
# ge 5 in next line should be length of file extension including . character, plus 1 
    [ ${#result} -ge 5 ] && outfile="/path/to/files/$result" || echo "Selection not made" 
fi 
cd "$dir" 

$ Le résultat sera vide si aucune sélection valide n'a été faite. J'ai ajouté une sélection fictive en haut de la liste qui renvoie une chaîne vide, de sorte que vous ne sélectionniez pas accidentellement le mauvais fichier en appuyant accidentellement sur Entrée juste après que le menu apparaisse. Si vous ne voulez pas cela, alors dans la ligne "for", supprimez le +2 dans "do j = $ ((2 * $ i + 2))" et aussi les deux lignes suivantes qui définissent un [0] et un [1] explicitement. Ce qui est déroutant à propos du whiptail, c'est qu'en lisant un tableau dans une situation comme celle-ci, il attend deux éléments de données par ligne, les deux étant affichés, le premier étant le résultat que vous voulez renvoyer si la ligne est attendue (dans certaines situations, il peut s'agir d'une lettre ou d'un chiffre) et le second est le texte descriptif que vous souhaitez. C'est pourquoi pour la première ligne j'utilise un [0] pour donner une chaîne vide comme résultat, et un [1] comme texte descriptif, mais à partir de là, le premier élément de la paire contient le nom de fichier (qui est ce que je Je veux retourner) et la seconde est une chaîne vide, puisque je ne veux pas afficher de texte autre que le nom de fichier sur ces lignes. Un message précédent disait que whiptail renvoyait un code d'erreur de 255 si le bouton d'annulation était enfoncé, mais ce n'était pas le cas pour la version que j'ai - il renvoie 1. Donc, je teste juste un code d'erreur de 0 et si c'est le cas je suppose que c'est une entrée valide, alors je teste une longueur de chaîne valide (plus que juste le nombre de caractères dans l'extension du fichier, y compris le caractère.) pour être sûr.

Questions connexes