How do you store a list of directories into an array in Bash (and then print them out)?
I want to write a shell script to show a li开发者_开发百科st 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 directories there are
I'm thinking this is some kind of array operation, but im not sure how to do this in shell script
example:
> whichdir
There are 3 dirs in the current path
1 dir1
2 dir2
3 dir3
which dir do you want?
> 3
you selected dir3!
$ 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/!
Array syntax
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]}!"
Find
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.
#! /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]}"
Update: my answer is wrong
Leaving it here to address a common misunderstanding, below the line is erroneous.
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
精彩评论