I want to write a shell script to show a list of directories entered by a user and then for a user to select one of the directories with an index number based on how many di
#! /bin/bash
declare -a dirs
i=1
for d in */
do
dirs[i++]="${d%/}"
done
echo "There are ${#dirs[@]} dirs in the current path"
for((i=1;i<=${#dirs[@]};i++))
do
echo $i "${dirs[i]}"
done
echo "which dir do you want?"
echo -n "> "
read i
echo "you selected ${dirs[$i]}"
Assuming you have the directories stored in an array:
dirs=(dir1 dir2 dir3)
You can get the length of the array thusly:
echo "There are ${#dirs[@]} dirs in the current path"
You can loop through it like so:
let i=1
for dir in "${dirs[@]}"; do
echo "$((i++)) $dir"
done
And assuming you've gotten the user's answer, you can index it as follows. Remember that arrays are 0-based so the 3rd entry is index 2.
answer=2
echo "you selected ${dirs[$answer]}!"
How do you get the file names into an array, anyways? It's a bit tricky. If you have find
that might be the best way:
readarray -t dirs < <(find . -maxdepth 1 -type d -printf '%P\n')
The -maxdepth 1
stops find from looking through subdirectories, -type d
tells it to find directories and skip files, and -printf '%P\n'
tells it to print the directory names without the leading ./
it normally likes to print.
To put the directories in an array you can do...
array=( $( ls -1p | grep / | sed 's/^\(.*\)/"\1"/') )
This will capture the dir names, including those with spaces.
Extracting from comments:
literal quotes don't have any effect on string-splitting, so array=( echo '"hello world" "goodbye world"' ) is an array with four elements, not two
@Charles Duffy
Charles also supplied the following link Bash FAQ #50 which is an extended discussion on this issue.
I should also draw attention to the link posted by @Dennis Williamson - why I shouldn't have used ls
$ ls -a
./ ../ .foo/ bar/ baz qux*
$ shopt -s dotglob
$ shopt -s nullglob
$ array=(*/)
$ for dir in "${array[@]}"; do echo "$dir"; done
.foo/
bar/
$ for dir in */; do echo "$dir"; done
.foo/
bar/
$ PS3="which dir do you want? "
$ echo "There are ${#array[@]} dirs in the current path"; \
select dir in "${array[@]}"; do echo "you selected ${dir}"'!'; break; done
There are 2 dirs in the current path
1) .foo/
2) bar/
which dir do you want? 2
you selected bar/!