2009-10-13 5 views
6

Я нашел отличную небольшую программу, которая позволит мне добавлять пользовательские графические интерфейсы к моим скриптам Bash;Сценарии BASH: выбор файла whiptail

Хлыстохвост

Однако whiptail man page не все, что полезно и не дает каких-либо примеров. После выполнения некоторых поисков Google я не понимаю, как создать простую да/нет меню с помощью Хлыстохвоста:

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

Но то, что я действительно хотел бы создать файл меню выбора с помощью Хлыстохвосту заменить некоторые старый код, я имею в несколько различные резервное копирование/восстановление Баш сценарии у меня есть:

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

Я предполагаю, что это должно быть сделано с помощью опции «--menu» из Хлыстохвост, но я не уверен, как идти об этом? Любые указатели? Или вы можете указать мне в сторону некоторых примеров whiptail?

+0

Я сделал небольшое изменение в своем ответе (формула восьмеричного преобразования). –

ответ

8

Построить массив имен файлов и тегов меню выберите:

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 

метод, как это будет работать, даже если есть имена файлов с пробелами. Если количество файлов велико, вам, возможно, придется разработать другую стратегию тегов.

Использование альфа-символов для тегов позволяет нажать букву для перехода к элементу. Числовые теги, похоже, не делают этого. Если вам это не нужно, вы можете устранить некоторую сложность.

Отображение меню:

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

Если код завершения 255, диалог был отменен.

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

Чтобы поймать выбор в переменной, используйте эту структуру (заменить вашу Хлыстохвост команду для "Хлыстохвост-команды"):

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

Или

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

Переменная $result будет содержат букву алфавита, которая соответствует файлу в массиве. К сожалению, Bash до версии 4 не поддерживает ассоциативные массивы. Вы можете вычислить индекс в массиве файла из письма, как это (обратите внимание на «лишние» одиночные кавычки):

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

Пример:

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

Обратите внимание: я отредактировал свой ответ, чтобы заменить предыдущую восьмеричную формулу преобразования, которая была ( почти) совершенно неправильной. –

+0

Для временных файлов вы можете использовать mktemp. Например, mytempfile=$(mktemp) ; echo "Hello world">$mytempfile; echo Contents of ${mytempfile}: $(cat $mytempfile) ; rm -f $mytempfile jbatista

+0

@jbatista: Это правда, но как это применимо? Здесь нет упоминаний о временных файлах. –

3

Whiptail - это легкая переоценка наиболее популярных функций dialog, используя Newt library. Я сделал быструю проверку, и многие функции в Whiptail, похоже, ведут себя как их коллеги в диалоге. Итак, учебник по диалогу должен вас начать. Вы можете найти один here, но Google - ваш друг, конечно. С другой стороны, extended example, вероятно, содержит много вдохновения для вашей проблемы.

0

Я попытался следующие, которые работали:

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

вы можете изменить это в множественным лайнера, а также, я добавил проверки для пустого списка:

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 

вам нужно для корректировки чисел, чтобы получить чистый интерфейс. И вы можете заменить "-" на что-нибудь еще, если хотите. Но если вы этого не сделаете, вы увидите 2 записи в строке.

К слову: выбранная запись напечатана на stderr.

Это может потребоваться некоторое улучшение, но для базовой идеи я думаю, что этого достаточно.

0

Это, кажется, одна из верхней результаты при поиске whiptail, и ни один из предыдущих результатов не работал для меня. Это то, что я заработал, используя:

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

$ result будет пустым, если действительный выбор не был произведен. Я добавил фиктивный выбор в верхней части списка, который возвращает пустую строку в результате, чтобы вы случайно не выбрали неправильный файл, случайно нажав Enter сразу после появления меню. Если вы этого не хотите, то в строке «для» удалите +2 в «do j = $ ((2 * $ i + 2))», а также следующие две строки, которые устанавливают [0] и [1] явно.

Непонятная вещь о whiptail заключается в том, что при чтении из массива в подобной ситуации он ожидает два элемента данных в строке, оба из которых отображаются, причем первый из них является результатом, который вы хотите вернуть, если линия ожидается (что в некоторых ситуациях может быть буква или число), а второе - любой дескриптивный текст, который вы можете захотеть. Поэтому для первой строки я использую [0], чтобы дать пустую строку в качестве результата, а [1] - как описательный текст, но оттуда в первом элементе в паре содержится имя файла (это то, что я на самом деле хотите вернуть), а вторая - пустая строка, так как я не хочу отображать на этих строках текст, отличный от имени файла.

Также предыдущий пост сказал, что whiptail возвратил код ошибки 255, если была нажата кнопка отмены, но это было не так для версии, которую я имею - она ​​возвращает 1. Поэтому я просто проверяю код ошибки 0 и если я полагаю, что это может быть допустимая запись, тогда я проверяю правильную длину строки (не просто количество символов в расширении файла, включая символ.).

Смежные вопросы