Create bash menu based on file list (map files to numbers)
To save the outputs of find
in a bash
array use this:
unset options i
while IFS= read -r -d $'\0' f; do
options[i++]="$f"
done < <(find /dir/ -maxdepth 1 -type f -name "*.war" -print0 )
-
read
reads the input fromfind
null delimited (-d $'\0'
).- The array
$options
is filled with the filenames.
- The array
-
find
searches only for files (-type f
) within the given directory (-maxdepth 1
) with ending.war
(-name "*.war"
) and prints them delimted by the null character (-print0
).
The select menu can be done like this:
select opt in "${options[@]}" "Stop the script"; do
case $opt in
*.war)
echo "War file $opt selected"
# processing
;;
"Stop the script")
echo "You chose to stop"
break
;;
*)
echo "This is not a number"
;;
esac
done
It works as follows:
1) /dir/old.war
2) /dir/debug.war
3) /dir/release.war
4) Stop the script
#? test
This is not a number
#? 2
War file /dir/debug.war selected
#? 4
You chose to stop
You could also use a shell glob to get the list of files. This approach has the advantage of not using an external program (find
) and of not needing any restriction on the type of file (*war
, for example) given:
#!/usr/bin/env bash
## Collect the files in the array $files
files=( ~/foo/war/* )
## Enable extended globbing. This lets us use @(foo|bar) to
## match either 'foo' or 'bar'.
shopt -s extglob
## Start building the string to match against.
string="@(${files[0]}"
## Add the rest of the files to the string
for((i=1;i<${#files[@]};i++))
do
string+="|${files[$i]}"
done
## Close the parenthesis. $string is now @(file1|file2|...|fileN)
string+=")"
## Show the menu. This will list all files and the string "quit"
select file in "${files[@]}" "quit"
do
case $file in
## If the choice is one of the files (if it matches $string)
$string)
## Do something here
echo "$file"
## Uncomment this line if you don't want the menu to
## be shown again
# break;
;;
"quit")
## Exit
exit;;
*)
file=""
echo "Please choose a number from 1 to $((${#files[@]}+1))";;
esac
done