I would like to create a simple interactive selection bash script, which should show a list of directories of a specific folder and depending on the first selection it should do a second selection in this folder. With these two selections, the script will do some specific things.
This is how the starting script looks like:
#!/bin/bash
title="Project"
prompt="Select project"
options=("A", "B") # How to use subfolders of a specific folder?
echo "$title"
PS3="$prompt "
select opt in "${options[@]}" "Quit"; do
case "$REPLY" in
1) echo "$opt";; # do something specific to this value
2) echo "$opt";; # do something specific to this value
$((${#options[@]} 1))) echo "Goodbye."; break;;
*) echo "Invalid option."; continue;;
esac
done
Instead of hardcoding options I would like to use this result:
for d in apps/*/ ; do basename "$d" ; done
How do I get this result as options
value?
And after selections, it should do the same thing for this selected folder:
for d in apps/$opt/*/ ; do basename "$d" ; done
Depending on this selection there should be done different things / commands / calculations.
Summary
User should select a subfolder of a specific directory (=app) and then select again a subfolder (=project). With this I do have two values (app and project) for further calculations.
CodePudding user response:
The wildcard will get expanded in any context.
options=( */ )
Depending on your users' (lack of) sophistication, you might want to postprocess the result; this will populate the array with A/ B/
where the trailing slash is important for selecting only directories.
(In many situations, the variable is an unnecessary and slightly wasteful indirection; if you don't care about postprocessing, you can simply say
select opt in */ "Quit"
directly. Depending on your use case, you might want or need to add a prefix ./
too, to disambiguate any directories which start with a minus sign.)
To explicitly run basename
on each entry, maybe use a loop to populate the array:
# local n
options=( )
for n in ./*/; do
options =("$(basename "$n")")
done
Often, you want to avoid external processes when you can; a parameter expansion will be slightly clunkier, but much more efficient.
Concentrating on just the select
problem, I guess you are looking for something like
select opt in */ "Quit"
do
case "$REPLY" in
"Quit") break;;
esac
select final in "app/$opt"/* "Quit"
do
case "$REPLY" in
"Quit") break;;
esac
echo "You chose $REPLY"
done
done