Search code examples
bashinputwhiptail

Bash - find string associated with number?


So, my script is supposed to prompt the user which file to select using whiptail, then read some things from the user selected file. Whiptail takes 2 arguments: The number of the list entry, and the list entry itself. When the user selects a list entry, Whiptail only returns the number of the selection. So, my question is, how do I reference the file that the user selected later on in the script? This is what I have so far:

whiptailargs=""
num=0
for file in device-configs/*
do
echo "File is $file"
let "num += 1"
if [[ ! "$file" == *" "* ]];
then
rem="device-configs/"
rem2=" "
whiptailargs="$whiptailargs"
whiptailargs="$whiptailargs$num"
whiptailargs="$whiptailargs $file "
fi
echo "Whiptail args: $whiptailargs"
done
mode=$(whiptail --title "Example" --menu "Choose an option" 15 60 4 $whiptailargs 3>&1 1>&2 2>&3)
num=""
echo $mode

EDIT: John1024's answer worked perfectly, and he explained it very well. Thanks!


Solution

  • We can accomplish that with two arrays. One array will keep the file names and the other will have the arguments that whiptail needs. Because we are use arrays, not variables, this can be safe to use even if file names have spaces or other difficult characters. Thus:

    flist=(device-configs/*)
    arglist=()
    for i in "${!flist[@]}"; do
       arglist+=("$i" "${flist[i]}")
    done
    mode=$(whiptail --title "Example" --menu "Choose an option" 15 60 4 "${arglist[@]}" 3>&1 1>&2 2>&3)
    if [ "$mode" ]
    then
        echo "$mode, ${flist[mode]}"
    else
        echo "Canceled."
    fi
    

    How it works

    • flist=(device-configs/*)

      This creates a bash array of all the names of the files of interest. This is safe even if the names contains spaces or other difficult characters.

    • arglist=()

      This creates an empty array.

    • for i in "${!flist[@]}"; do arglist+=("$i" "${flist[i]}"); done

      This fills arglist with the values needed for whiptail.

    • mode=$(whiptail --title "Example" --menu "Choose an option" 15 60 4 "${arglist[@]}" 3>&1 1>&2 2>&3)

      This calls whiptail and saves the result. Again, the form "${arglist[@]}" is safe even if file names contains spaces, etc.

    • echo "$mode, ${flist[mode]}"

      This reports the results. We have put this in an if statement that detects if the user pressed cancel rather than select an answer.