Сценарий оболочки Linux: динамическое определение папок в каталоге сценариев и их добавление в массив [дубликат]

На всякий случай я решил это, просто комментируя следующую строку:

netbeans_jdkhome="/usr"

To

#netbeans_jdkhome="/usr"

Edit:

Каталог приведенного выше кода находится внутри файла ~ / netbeans-8.1 / etc / netbeans

20
задан qodeninja 20 December 2010 в 22:55
поделиться

5 ответов

$ 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/!
37
ответ дан Dennis Williamson 18 August 2018 в 13:34
поделиться
  • 1
    +1 для select. Это одно из тех скрытых сокровищ, которые люди часто пытаются изобретать, потому что они не знают, что они существуют – SiegeX 22 December 2010 в 00:02
  • 2
    очень опрятный, что array=(*/) трюк только для расширения dirs – Carlos Campderrós 29 January 2014 в 14:25
  • 3
    Он работает, если имя каталога содержит пробел? – Khurshid Alam 15 August 2016 в 08:27
  • 4
    @KhurshidAlam: да – Dennis Williamson 15 August 2016 в 17:13

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

1
ответ дан Brian Agnew 18 August 2018 в 13:34
поделиться
  • 1
    Это правда, но, скорее, дико неполно, пока / пока не сообщит, как сохранить результат glob для каталогов в такой массив. Пример из одной строки, т.е. array=( */ ), сделал бы это довольно много хорошего. – Charles Duffy 21 June 2018 в 21:06
  • 2
    Кстати, что значит «сейчас»? Массивы были доступны с момента первоначального выпуска bash 2.0 в 1996 году. (Кстати, я бы предложил wiki [bash-hackers] , BashGuide или официальное руководство в качестве справочного материала, АБС - это то, что W3Schools для JavaScript и HTML - полное устаревшей информации и примеров плохой практики, но с большим количеством сока Google) – Charles Duffy 21 June 2018 в 21:07
#! /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]}"
4
ответ дан Jester 18 August 2018 в 13:34
поделиться
  • 1
    oh wow это работает, кроме как вы его не включаете. и .. dirs? – qodeninja 21 December 2010 в 00:23
  • 2
    Я тестировал это, он не должен включать их в любом случае. – ocodo 21 December 2010 в 02:31
  • 3
    он выводит * в качестве одного из параметров LOL – qodeninja 21 December 2010 в 23:42
  • 4
    посмотрите на встроенный select, вы так изобретаете колесо – SiegeX 22 December 2010 в 00:05

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

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

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, поэтому 3-я запись - это индекс 2.

answer=2

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

Найти

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

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

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

19
ответ дан John Kugelman 18 August 2018 в 13:34
поделиться
  • 1
    @johnstamos, пробелы - это не единственная проблема - если у вас есть каталог, созданный с помощью mkdir '*', вам также нужно беспокоиться о том, что он расширяется, и каждый другой каталог в этом месте будет дважды указан , если только вы не запустили set -f, чтобы отключить глобус. – Charles Duffy 21 June 2018 в 21:11

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

Оставив его здесь, чтобы встретить общее недоразумение, ниже строки ошибочно.


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

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

Это приведет к захвату имен dir, в том числе к пробелам.


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

литеральные кавычки не оказывают никакого влияния на разделение строк, поэтому array = (echo «hello world» «goodbye world») представляет собой массив с четырьмя элементами, а не двумя

@Charles Duffy

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

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

-1
ответ дан ocodo 18 August 2018 в 13:34
поделиться
  • 1
    Это не удастся, если у каких-либо каталогов есть место в их именах. – Dennis Williamson 21 December 2010 в 01:57
  • 2
    Хорошая точка, обновленная. – ocodo 21 December 2010 в 02:19
  • 3
    Нет, это не проблема. Это потому, что вы используете ls. См. некоторые причины не для . – Dennis Williamson 22 December 2010 в 02:00
  • 4
    Обновление работает, хотя, предоставлено for d in */ do лучше. Связанная статья отметила, что у меня никогда не было проблем с именами искажений ls, но стоит знать, что плохое имя файла будет обработано плохо, спасибо. – ocodo 22 December 2010 в 04:02
  • 5
    @ocodo, нет, обновление не работает; литеральные кавычки не влияют на разделение строк, поэтому array=( echo '"hello world" "goodbye world"' ) представляет собой массив с четырьмя элементами, а не двумя - первым из этих элементов является "hello, а второй - world". См. BashFAQ # 50 для обсуждения других ошибок, вызванных тем же недоразумением. – Charles Duffy 21 June 2018 в 21:05