2015-02-08 40 views
3

我正在编写bash脚本,我在某个目录中有多个子文件夹,我想列出子文件夹的名称和将结果读入一个数组中,省略了一个名为'cmmdm'的文件夹。一旦我已经读入阵列的名字,我想要生成一个菜单,每个子菜单名称作为一个选项,然后我将根据用户做出的选择,在给定的子文件夹上执行一个功能。bash列出文件夹中的所有子目录,将它们写入数组以供在菜单中使用

编辑: 对不起应该已经向我最初的代码:

#!/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 2015-02-08 12:22:08

+0

在Bash中,使用[extentded globs](http://www.gnu.org/software/bash/manual/bashref.html#Pattern-Matching):'shopt -s extglob nullglob; array =(dir /!(cmmdm)/)'。 – 2015-02-08 12:27:51

+0

嗨,对不起,我已添加我的inital代码以查看im卡住的位置 – 2015-02-08 13:45:37

回答

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(确切的说,全场比赛)。要具有不以ab结尾的所有子目录:

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

没有冒犯,我在周末之前对bash的全部知识都是零,所以我没有从一个好的地方出发。你的实现工作完美,并有很好的注释,以便我可以简单地将它扩展到我的脚本,谢谢:] – 2015-02-09 22:29:59

2

难道find可以帮你吗?

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

或者也许是for-loop(这将需要你自己创建数组)?

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

我已被告知,使用“内部字段分隔符”(IFS)如下图所示,是一个更为安全的解决方案(针对怪事保护,如白色字符,在FILD /目录名)

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

嗨,感谢您的回复,对不起,我忘了添加我的初始代码,看看我卡住的地方,我用ls,但可能会发现会更好,无论哪种方式我坚持将结果添加到数组 – 2015-02-08 13:47:12

+1

解析'ls'作为一个参数是一个潜在的不好主意(如果名称中有空格,则是灾难性的)[ParsingLs](http://mywiki.wooledge.org/ParsingLs)。 我从来没有真的必须自己建立一个数组(我通常会找到一个方法),你见过[this](http://stackoverflow.com/questions/1951506/bash-add-value-to-array -without-specified-a-key)讨论?目前我无法对此进行测试,但我会这样做,因为这对我来说也是一种潜在的情况。 – 2015-02-08 16:36:45

相关问题