2009-10-13 9 views
6

Znalazłem bardzo mały program, który pozwoli mi dodać przyjazny dla użytkownika GUI do moich Bash skryptów;BASH skrypty: Whiptail plik Wybierz

Whiptail

Jednak whiptail man page nie jest tak pomocny i nie daje żadnych przykładów. Po jakiejś wyszukiwania Google I zrozumieć, jak stworzyć prosty tak/nie menu używając 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 

Ale to, co naprawdę chciałbym zbudować plik Wybierz menu za pomocą tejowatych zastąpić jakiś stary kod mam w kilku Kopia zapasowa/przywracanie różne skrypty bash mam:

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

Zakładam, to musi być zrobione poprzez opcję „--menu” z tejowatych, ale nie jestem pewien, jak się do tego zabrać? Jakieś wskazówki? Albo można wskazać mnie w kierunku niektórych tejowatych przykładów?

+0

Wprowadziłem niewielką zmianę do mojej odpowiedzi (ósemkowa formuła konwersji). –

Odpowiedz

8

zbudować tablicę nazw plików i menu wybierz tagi:

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 

Sposób jak to będzie działać, nawet jeżeli istnieją nazwy plików ze spacjami. Jeśli liczba plików jest duża, być może trzeba będzie opracować kolejną strategię tagów.

Używanie znaków alfa dla znaczników pozwala wcisnąć do nas, aby przejść do żądanej pozycji. Znaczniki liczbowe nie wydają się tego robić. Jeśli nie potrzebujesz takiego zachowania, możesz wyeliminować pewną złożoność.

wyświetlania menu:

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

Jeśli kod wyjścia jest równy 255, okno zostało anulowane.

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

Aby złapać wybór w zmiennej, należy użyć tej struktury (zastąpił swoją komendę tejowatych dla "tejowatych-polecenia"):

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

Albo

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

Zmienna $result będzie zawierają literę alfabetu, która odpowiada plikowi w tablicy. Niestety, Bash przed wersją 4 nie obsługuje tablic asocjacyjnych. Można obliczyć indeks do tablicy pliku z literą jak ten (zawiadomienie „ekstra” apostrof):

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

Przykład:

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

Uwaga: zredagowałem swoją odpowiedź, aby zastąpić poprzednią ósemkową formułę konwersji, która była ( prawie) całkowicie błędna. –

+0

W przypadku plików tymczasowych można użyć mktemp. Na przykład: mytempfile=$(mktemp) ; echo "Hello world">$mytempfile; echo Contents of ${mytempfile}: $(cat $mytempfile) ; rm -f $mytempfile jbatista

+0

@jbatista: To prawda, ale jak to ma zastosowanie? Tutaj nie ma żadnej wzmianki o plikach tymczasowych. –

3

Whiptail to lekka reimplementacja najpopularniejszych funkcji dialog, przy użyciu Newt library. Zrobiłem szybki test i wiele funkcji w Whiptail zdaje się zachowywać jak ich odpowiedniki w dialogu. Dlatego samouczek dialogowy powinien zacząć. Możesz znaleźć jeden here, ale Google jest oczywiście twoim przyjacielem. Z drugiej strony, extended example prawdopodobnie zawiera wiele inspiracji dla swojego problemu.

0

Próbowałem następujących, który pracował:

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

można to zmienić w wielokrotnej liniowej, a także dodałem sprawdzanie pustej listy:

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 

trzeba aby dostosować liczby w celu uzyskania czystego interfejsu. I możesz zastąpić "-" cokolwiek innego, jeśli chcesz. Ale jeśli nie, zobaczysz 2 wpisy na linię.

W sposób: zaznaczone są drukowane na stderr.

To może potrzebować trochę więcej się poprawia, ale na podstawowej idei myślę, że to wystarczy.

0

to wydaje się być jednym z najlepszych wyniki wyszukiwania whiptail i żaden z poprzednich wyników nie był dla mnie skuteczny. Właśnie to zlikwidowałem, używając:

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

Wynik będzie pusty, jeśli nie wybrano prawidłowego wyboru. Dodałem fikcyjną selekcję u góry listy, która zwraca w rezultacie pusty ciąg znaków, aby przypadkowo nie wybrać niewłaściwego pliku przez przypadkowe naciśnięcie Enter zaraz po pojawieniu się menu. Jeśli tego nie chcesz, to w linii "for" usuń +2 w "do j = $ ((2 * $ i + 2))", a także następujące dwie linie, które ustawiają [0] i [1] jawnie.

Mylące zagadnienie dotyczące whiptail polega na tym, że podczas odczytu z tablicy w takiej sytuacji oczekuje dwóch pozycji danych na linię, z których oba są wyświetlane, z których pierwszy jest wynikiem, który ma zostać zwrócony, jeśli linia jest oczekiwana (co w niektórych sytuacjach może to być litera lub cyfra), a drugi to dowolny opisowy tekst, który możesz chcieć. Dlatego w pierwszym wierszu używam [0], aby podać pusty ciąg, a [1] jako tekst opisowy, ale stamtąd pierwszy element w parze zawiera nazwę pliku (co jest tym, co faktycznie want return), a drugi jest pustym łańcuchem, ponieważ nie chcę wyświetlać żadnego tekstu poza nazwą pliku w tych liniach.

Również poprzedni post powiedział, że whiptail zwrócił kod błędu 255, jeśli został naciśnięty przycisk anulowania, ale tak nie było w przypadku wersji, którą mam - zwraca 1. Więc po prostu testuję kod błędu 0 i jeśli jest to zakładam, że może to być prawidłowy wpis, to testuję na poprawną długość ciągu znaków (więcej niż tylko liczba znaków w rozszerzeniu pliku, w tym znak.), aby mieć pewność.