Как сохранить список каталогов в массиве Bash (а затем распечатать их)? - PullRequest
23 голосов
/ 21 декабря 2010

Я хочу написать сценарий оболочки для отображения списка каталогов, введенных пользователем, а затем для пользователя, чтобы выбрать один из каталогов с индексным номером на основе количества каталогов

Я думаю, что это какая-то операция с массивом, но я не уверен, как это сделать в сценарии оболочки

пример:

> whichdir
There are 3 dirs in the current path
1 dir1
2 dir2
3 dir3
which dir do you want? 
> 3
you selected dir3!

Ответы [ 5 ]

39 голосов
/ 21 декабря 2010
$ 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/!
21 голосов
/ 21 декабря 2010

Синтаксис массива

Предполагается, что каталоги хранятся в массиве:

dirs=(dir1 dir2 dir3)

Вы можете получить длину массива следующим образом:

echo "There are ${#dirs[@]} dirs in the current path"

Выможет проходить через него следующим образом:

let i=1

for dir in "${dirs[@]}"; do
    echo "$((i++)) $dir"
done

И, предполагая, что вы получили ответ пользователя, вы можете проиндексировать его следующим образом.Помните, что массивы основаны на 0, поэтому третья запись - это индекс 2.

answer=2

echo "you selected ${dirs[$answer]}!"

Find

Как вы в любом случае получаете имена файлов в массив?Это немного сложно.Если у вас есть find, это может быть лучшим способом:

readarray -t dirs < <(find . -maxdepth 1 -type d -printf '%P\n')

-maxdepth 1 останавливает поиск при просмотре подкаталогов, -type d сообщает ему найти каталоги и пропускает файлы, а -printf '%P\n' сообщаетэто, чтобы напечатать имена каталогов без начального ./, это обычно любит печатать.

4 голосов
/ 21 декабря 2010
#! /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]}"
1 голос
/ 21 декабря 2010

Bash теперь поддерживает одномерные массивы . Поскольку в массивах не должно быть смежных элементов, они больше похожи на карты.

0 голосов
/ 21 декабря 2010

Обновление: мой ответ неверен

Оставить его здесь для устранения распространенного недоразумения ниже строки ошибочно.


Чтобы поместить каталоги в массив, вы можете сделать ...

array=( $( ls -1p | grep / | sed 's/^\(.*\)/"\1"/') )

Это захватит имена режиссеров, в том числе с пробелами.


Извлечение из комментариев:

буквенные кавычки не влияют на разбиение строк, поэтому array = (echo '"hello world" "goodbye world"') - это массив из четырех элементов, а не двух

@ Чарльз Даффи

Чарльз также предоставил следующую ссылку Bash FAQ # 50 , которая является расширенным обсуждением по этому вопросу.

Я должен также обратить внимание на ссылку, опубликованную @Dennis Williamson - , почему я не должен был использовать ls

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...