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!
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
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.