我需要列出目录的所有子目录,但不包括与作为参数给出的列表匹配的子目录:“SUBDIR1,SUBDIR2,...,SUBDIRN”。
我找到了解决方案(来自许多来源),即使用 ls 和 glob 模式。为了测试这个概念,我在命令行中尝试了以下似乎有效的序列:
DIR="/path/to/dirs"
EXCLUDELIST="subdir1,subdir2"
#transform in a glob pattern for excluding given subdirectories
EXCLUDE="!(${EXCLUDELIST//,/|})"
LIST=$(cd $DIR && ls -l -d $EXCLUDE | grep -E "(^d)" | awk '{print $9}')
但是,当我将其放入 bash 脚本中时未修改我收到这个错误
ls: cannot access !(subdir1|subdir2): No such file or directory
当我将此代码放入脚本中时我做错了什么?
答案1
Dennis 告诉了你为什么你的脚本会失败,但我想建议一种更简单(更安全)的方法。解析ls
是几乎总是一个坏主意,它很容易因文件名中包含空格、换行符或其他奇怪字符而中断,并且无法跨 LOCALE 设置移植。此外,您的命令非常复杂,涉及多个步骤。为什么不全部在 中完成find
?
DIR="/path/to/dirs"
EXCLUDELIST="subdir1,subdir2"
## Build the regular expression
EXCLUDE="${EXCLUDELIST//,/|.*}"
LIST=$(find "$DIR" -type d -regextype posix-awk -not -regex ".*$EXCLUDE.*")
顺便说一句,你的脚本将会失败,因为你构建了 glob前 cd
-ing into$DIR
因此它将根据当前目录的内容进行构建。
答案2
交互式和非交互式 bash shell 的行为并不相同。其中的一个区别是 shell 选项外接球对于交互式 shell 来说,它默认是启用的(至少在我的 bash 版本中是这样),但是对于非交互式 shell 来说,它不启用。
要修复脚本,请启用外接球使用以下命令:
shopt -s extglob