Select command with variable options having spaces or null contents

Hi,

I'm having an issue trying to produce a hierarchical directory menu that has either any directories listed in a specific directory as options or options with spaces in the option content or null content.

So the menu function gets passed a base directory, it then lists any .sh scripts in that directory or any other sub directories.

A select command lists the directories as seperate options, if there any shell scripts then an option "Run scripts in this dir" is given.

My problem is that if there are no shell scripts it gives a blank option in the select command, also a blank if there are no sub directories.

#!/usr/bin/ksh
 
. $HOME/.profile
cd $HOME
 
function menu {
thisDir=$1
opt1=""
opt2=""
menuDone=false
PS3="   Select the directory sub path or option required : "
 
while [[ $menuDone = false ]];do
 
  if ls -l $thisDir|grep "^d" >/dev/null;then
    opt1=`ls -l ${thisDir}|grep "^d"|awk '{print $9}'`
  fi
 
  if [[ -f $thisDir/*.sh ]];then
    opt2="Run scripts listed in this directory"
  fi
 
  opt3="Return to previous menu"
  opt4="Quit"
 
  select choice in "$opt1" "$opt2" "$opt3" "$opt4";do
        case $choice in
                     "$opt2" ) runThisDirScripts
                               break ;;
                     "$opt3" ) return ;;
          q|Q|quit|Quit|QUIT ) exit ;;
                          '' ) print "\n\n  Invalid Option !"
                               sleep 3
                               break ;;
                           * ) if [[ ! -z ${REPLY} ]];then
                                 menu $thisDir/$choice
                                 break
                               fi ;;
        esac
        print $choice
  done
done
}
 
#-- MAIN
dir=/export/home/aspsys/deploy/upgrade/configBackend
menu "$dir"

---------- Post updated at 12:55 PM ---------- Previous update was at 12:51 PM ----------

sorry, that line with REPLY should read $choice

---------- Post updated at 01:27 PM ---------- Previous update was at 12:55 PM ----------

I made some changes but still have the blank options problem

#!/usr/bin/ksh
. $HOME/.profile
cd $HOME
function menu {
menuDone=false
PS3="   Select the directory sub path or option required : "
while [[ $menuDone = false ]];do
  clear
  thisDir=$1
  opt1=""
  opt2=""
  if ls -l $thisDir|grep "^d" >/dev/null;then
    opt1=`ls -l ${thisDir}|grep "^d"|awk '{print $9}'`
  fi
  if [ -f $thisDir/*.sh ];then
    opt2="Run scripts listed in this directory"
    print "\n\n  The following scripts are in this level (${thisDir}) :\n"
    for file in `ls ${thisDir}/*.sh`;do
      echo "  `basename ${file}`"
    done
    echo
  fi
  opt3="Return to previous menu"
  opt4="Quit"
  select choice in "$opt1" "$opt2" "$opt3" "$opt4";do
        case $choice in
                     "$opt2" ) runThisDirScripts
                               break ;;
                     "$opt3" ) return ;;
          q|Q|quit|Quit|QUIT ) exit ;;
                          '' ) print "\n\n  Invalid Option !"
                               sleep 3
                               break ;;
                           * ) if [[ ! -z $choice ]];then
                                 menu "$thisDir/$choice"
                                 break
                               fi ;;
        esac
        print $choice
  done
done
}
 
#-- MAIN
dir=/export/home/aspsys/deploy/upgrade/configBackend
menu "$dir"

Can you share the output what this produces?

I created some test dirs and so the example output with say a base dir structure of (using find) :

.
./dir1
./dir1/script2.sh
./dir1/script1.sh
./dir2

first iteration produces :

 
1) dir1
2) dir2
3)
4) Return to previous menu
5) Quit
   Select the directory sub path or option required :

select option 1 and we get :

 
 
The following scripts are in this level (/export/home/aspsys/scripts/andy/testdir1/dir1) :
 
  script1.sh
  script2.sh
 
1) Run scripts listed in this directory
2) Return to previous menu
3) Quit
   Select the directory sub path or option required :

Its the blank option in the first iteration that I cant get, maybe I need just a single concatenated option in the select command but when I try it it seperates the options with spaces in into seperate selects...

Try to run it in debug mode!!

set -x

Thanks but didn't help pinpoint what quotes I need around which variables..

The problem (as I see it, perhaps I'm looking at it wrong) is that I have say for example for variables being passed in the select command, one is a list one is a single word string, one is a string with spaces and one is either a string with spaces or nothing.

The list is done by having $var, the string is done by having "$var", however having "$var" means that a blank string is parsed if it contains nothing which select parses as a blank option... I think.

So by your script,
1st run
opt1 => dir1 dir2
opt2 => <empty>
opt3 => Return to previous menu
opt4 => Quit

select choice in "$opt1" "$opt2" "$opt3" "$opt4" expands as select choice in dir1 dir2 <empty> "Return to previous menu" "Quit"

So the display should be

1) dir1 
2) dir2
3)
4) Return to previous menu
5) Quit
   Select the directory sub path or option required :

so when you select option 1 (dir1) what will be the input??

ah, sorry, yes, I updated the code inbetween posting originally and trying to get it right

Now I have :

select choice in $opt1 "$opt2" "$opt3" "$opt4";do

which gives :

1) dir1
2) dir2
3)
4) Return to previous menu
5) Quit
   Select the directory sub path or option required :

but it still leaves the blank option.

I have tried also :

select choice in $opt1 $opt2 "$opt3" "$opt4";do

which does remove the blank option in the first iteration but then makes the 2nd iteration split out the string into seperate options :

1) dir1
2) dir2
3) Return to previous menu
4) Quit
   Select the directory sub path or option required : 1
 
 
  The following scripts are in this directory /export/home/aspsys/scripts/andy/testdir1/dir1) :
 
  script1.sh
  script2.sh
 
1) Run
2) scripts
3) listed
4) in
5) this
6) directory
7) Return to previous menu
8) Quit
   Select the directory sub path or option required :

---------- Post updated at 06:56 PM ---------- Previous update was at 05:36 PM ----------

I managed a solution using arrays instead :

#!/usr/bin/ksh
. $HOME/.profile
cd $HOME
function menu {
menuDone=false
PS3="   Select the directory sub path or option required : "
while [[ $menuDone = false ]];do
 
  clear
  thisDir=$1
  set -A menuList --
  idx=0
 
  for d in $(ls -l ${thisDir}|grep "^d"|awk '{print $9}');do
    menuList[idx]=$d
    idx=$(($idx+1))
  done
 
  if [ -f $thisDir/*.sh ];then
    menuList[idx]="Run scripts listed in this directory"
    idx=$(($idx+1))
    print "\n\n  The following scripts are in this directory (${thisDir}) :\n"
    for file in `ls ${thisDir}/*.sh`;do
      echo "  `basename ${file}`"
    done
    echo
  fi
 
  menuList[idx+1]="Return to previous menu"
  menuList[idx+2]="Quit"
 
  select choice in "${menuList[@]}";do
        case $choice in
           "Run scripts listed in this directory" ) runThisDirScripts
                                                    break ;;
                        "Return to previous menu" ) return ;;
                               q|Q|quit|Quit|QUIT ) exit ;;
                                               '' ) print "\n\n  Invalid Option !"
                                                    sleep 3
                                                    break ;;
                                                * ) if [[ ! -z $choice ]];then
                                                      menu "$thisDir/$choice"
                                                      break
                                                    fi ;;
        esac
        print $choice
  done
done
}
 
#-- MAIN
dir=/export/home/aspsys/scripts/andy/testdir1
menu "$dir"

I would interested in anything more elegant, it still looks a little clunky