2009-10-13 3 views
6

나는 배쉬 스크립트에 사용자 친화적 인 GUI를 추가 할 수있는 훌륭한 작은 프로그램을 발견했다.BASH 스크립트 : whiptail 파일 선택

whiptail man page이 모두 도움이되지 않습니다와 예제를 제공하지 않습니다 그러나 채찍 꼬리

. 일부 구글 검색을 수행 한 후 나는/어떤 메뉴를 사용하여 채찍 꼬리 간단한 예를 만드는 방법을 이해하지 :

#! /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'옵션을 통해 수행해야합니다 가정,하지만 난 그것에 대해 이동하는 방법을 잘 모르겠습니다 : 다른 백업/복원 bash는 스크립트는 내가 가진? 포인터가 있습니까? 아니면 몇 가지 예를 들어 설명해 줄 수 있습니까?

+0

나는 내 대답 (8 진수 변환 공식)에 약간의 변경을가했습니다. –

답변

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 것 배열의 파일에 해당하는 알파벳 문자를 포함합니다. 아쉽게도 버전 4 이전의 Bash는 연관 배열을 지원하지 않습니다.

((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

참고 : 나는 ( 거의) 완전히 틀린 이전의 8 진수 변환 공식을 대체하기 위해 내 대답을 편집했습니다. –

+0

임시 파일의 경우 mktemp를 사용할 수 있습니다. 예를 들어, mytempfile=$(mktemp) ; echo "Hello world">$mytempfile; echo Contents of ${mytempfile}: $(cat $mytempfile) ; rm -f $mytempfile jbatista

+0

@bbatista : 맞습니다. 어떻게 적용 할 수 있습니까? 여기에 임시 파일에 대한 언급이 없습니다. –

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" 

$ 유효한 선택이없는 경우 결과는 비게됩니다. 결과적으로 빈 문자열을 반환하는 목록 상단에 더미 선택을 추가 했으므로 실수로 메뉴가 나타나면 Enter 키를 눌러 실수로 잘못된 파일을 선택하지 않게됩니다. 원하지 않으면 "for"줄에서 "do j = $ ((2 * $ i + 2))"의 +2를 제거하고 [0]과 a를 설정하는 다음 두 줄을 제거하십시오. [1] 명시 적으로.

whiptail에 대한 혼란스러운 점은 이와 같은 상황에서 배열을 읽을 때 두 행 모두 표시된다는 것입니다. 두 행 모두 표시됩니다. 첫 행은 예상되는 행의 결과입니다. 어떤 경우에는 문자 또는 숫자가 될 수 있습니다.) 두 번째는 원하는 설명 텍스트입니다. 그래서 첫 번째 줄에는 [0]을 사용하여 빈 문자열을 결과로 제공하고 [1]을 설명 텍스트로 사용하지만 쌍의 첫 번째 항목에는 파일 이름이 포함됩니다 (실제로는 원하는 반환 된) 및 두 번째 빈 문자열입니다, 나는 그 줄에 파일 이름 이외의 텍스트를 표시하고 싶지 않기 때문에.

이전 게시물에 따르면 취소 버튼을 누르면 whiptail에서 255의 오류 코드를 반환하지만 이는 내가 가지고있는 버전에 해당하지 않습니다. 그래서 1을 반환합니다. 그래서 나는 단지 0과 그것이 올바른 항목 일 수 있다고 가정한다면, 유효한 문자열 길이 (.ext를 포함한 파일 확장자의 문자 수 이상)를 테스트합니다.

관련 문제