Home > Blockchain >  Interactive bash script for two selections: folder and subfolder
Interactive bash script for two selections: folder and subfolder

Time:10-17

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
  •  Tags:  
  • bash
  • Related