2015-02-08 4 views
3

Я нахожусь в середине написания сценария bash, у меня есть несколько подпапок в определенном каталоге, я хочу перечислить имена подпапок и прочитайте результаты в массив, исключающий определенную одну папку с именем «cmmdm» из результатов. Как только я прочитал имена в массиве, я хочу сгенерировать меню с каждым именем подменю в качестве выбора, который затем буду выполнять функцию в данной подпапке в зависимости от того, какой пользователь делает.bash перечислить все подкаталоги в папке, записать их в массив для использования в меню

EDIT: жаль, следовало бы добавить свой исходный код:

#!/bin/bash 
# - create array 
declare -a CDARRAY 

# - set 0 to exit in prep for menu 
CDARRAY[0]=exit 

# - create a counter to use in while loop 
count=1 

# - while loop to itterate through folder and add each folder except cmmdm into array 
ls -d /home/nginx/domains/* | { 
    while read CMMDOMAIN ; do 

      if [ $CMMDOMAIN != "/home/nginx/domains/cmmdm" ] 
      then 
      $CDARRAY[$count]=$CMMDOMAIN 
      echo $CDARRAY[$count] 
      count=$[count + 1] 
      fi 

    done 
} 

Это пройти через папку и не игнорировать «cmmdm» однако мой код, чтобы добавить переменный CMMDOMAIN в массиве является неправильным. Я никогда не писал сценарий в bash раньше, поэтому я думаю, что, вероятно, я получил синтаксис неправильно или отсутствует некоторые фигурные скобки или что-то.

+0

достаточно просто. Почему бы вам не попробовать? Вы где-то застряли? – SMA

+0

В Bash, используя [расширенные глобусы] (http://www.gnu.org/software/bash/manual/bashref.html#Pattern-Matching): 'shopt -s extglob nullglob; array = (dir /! (cmmdm) /) '. –

+0

Здравствуйте, извините, я добавил свой код, чтобы увидеть, где im stuck –

ответ

5

В вашем коде есть много проблем, слишком много для обсуждения здесь (без обид).

Вот полный пример, который будет отображаться меню, как вы хотите, и делает некоторые общие проверки:

#!/bin/bash 

shopt -s extglob nullglob 

basedir=/home/nginx/domains 

# You may omit the following subdirectories 
# the syntax is that of extended globs, e.g., 
# omitdir="cmmdm|not_this_+([[:digit:]])|keep_away*" 
# If you don't want to omit any subdirectories, leave empty: omitdir= 
omitdir=cmmdm 

# Create array 
if [[ -z $omitdir ]]; then 
    cdarray=("$basedir"/*/) 
else 
    cdarray=("$basedir"/!($omitdir)/) 
fi 
# remove leading basedir: 
cdarray=("${cdarray[@]#"$basedir/"}") 
# remove trailing backslash and insert Exit choice 
cdarray=(Exit "${cdarray[@]%/}") 

# At this point you have a nice array cdarray, indexed from 0 (for Exit) 
# that contains Exit and all the subdirectories of $basedir 
# (except the omitted ones) 
# You should check that you have at least one directory in there: 
if ((${#cdarray[@]}<=1)); then 
    printf 'No subdirectories found. Exiting.\n' 
    exit 0 
fi 

# Display the menu: 
printf 'Please choose from the following. Enter 0 to exit.\n' 
for i in "${!cdarray[@]}"; do 
    printf ' %d %s\n' "$i" "${cdarray[i]}" 
done 
printf '\n' 

# Now wait for user input 
while true; do 
    read -e -r -p 'Your choice: ' choice 
    # Check that user's choice is a valid number 
    if [[ $choice = +([[:digit:]]) ]]; then 
     # Force the number to be interpreted in radix 10 
     ((choice=10#$choice)) 
     # Check that choice is a valid choice 
     ((choice<${#cdarray[@]})) && break 
    fi 
    printf 'Invalid choice, please start again.\n' 
done 

# At this point, you're sure the variable choice contains 
# a valid choice. 
if ((choice==0)); then 
    printf 'Good bye.\n' 
    exit 0 
fi 

# Now you can work with subdirectory: 
printf "You chose subdirectory \`%s'. It's a good choice.\n" "${cdarray[choice]}" 

Комментарии должны объяснить довольно ясно, что происходит. Техника, используемая для построения массива, и это была цель вашего вопроса, - extended globs. Например:

shopt -s extglob nullglob 
cdarray=(/home/nginx/domains/!(cmmdm)/) 

заполнит cdarray со всеми подкаталоги /home/nginx/domains/, которые не соответствуют cmmdm (точный, полный матч). Для того, чтобы иметь все подкаталоги, которые не заканчиваются с a или b:

shopt -s extglob nullglob 
cdarray=(/home/nginx/domains/!(*[ab])/) 
+0

Без обид, все мои знания о bash, предшествовавшие выходным, были нулевыми, так что я не начинал с хорошего места. Ваша реализация работает отлично и была очень хорошо аннотирована, так что я могу просто расширить ее в свой скрипт, спасибо:] –

2

Может ли find быть чем-то для вас?

DIRS=$(find ${PWD} -maxdepth 1 -type d) 
echo ${DIRS} 

Или, может быть, для цикла (это потребует от вас сделать массив самостоятельно)?

for DIR in $(find ${PWD} -maxdepth 1); do if $(test -d ${DIR}); then echo $(basename ${DIR}); fi; done 

Мне сказали, что с помощью «Field Separator Internal» (IFS), как показано ниже, еще более безопасное решение (защита от странности, например, белые символы, в FILD/имена каталогов)

while IFS= read -r DIR; do echo "${DIR}"; done < <(find . -maxdepth 1 -type d -printf "%P\n") 
+0

Привет, спасибо за ответ, извините, что я забыл добавить свой первоначальный код, чтобы увидеть, где я застрял, я использовал ls, но, возможно, найти было бы лучше, так или иначе я застрял в добавлении результатов в массив –

+1

Parsing 'ls' как аргумент - потенциально плохая идея (катастрофическая, если у вас есть пробелы в именах) [ParsingLs] (http://mywiki.wooledge.org/ParsingLs). Мне никогда не приходилось строить массив самостоятельно (обычно я общаюсь с ним), вы видели [это] (http://stackoverflow.com/questions/1951506/bash-add-value-to-array -without-specifying-a-key)?Я не в состоянии проверить это на данный момент, но я буду, поскольку это потенциальный случай для меня и в будущем. –

Смежные вопросы