带有 glob 的 ls 在 bash 脚本中不起作用

pab*_*cin 11 bash command-line

我需要列出目录的所有子目录,不包括那些与作为参数给出的任何列表匹配的子目录:“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}')
Run Code Online (Sandbox Code Playgroud)

但是,当我将它放入未修改的 bash 脚本中时,我收到此错误

ls: cannot access !(subdir1|subdir2): No such file or directory
Run Code Online (Sandbox Code Playgroud)

将此代码放入脚本时我做错了什么?

Den*_*nis 12

交互式和非交互式 bash shell 的行为不同。许多不同之处之一是 shell 选项extglob默认为交互式 shell 启用(至少在我的 bash 版本中),但不适用于非交互式 shell。

要修复您的脚本,使用以下命令启用extglob

shopt -s extglob
Run Code Online (Sandbox Code Playgroud)


ter*_*don 5

丹尼斯告诉你为什么你的脚本失败,但我想建议一种更简单(更安全)的方法来做到这一点。解析几乎总是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.*")
Run Code Online (Sandbox Code Playgroud)

顺便说一句,您的脚本将在您编写时失败,因为您在-ing into之前 构建了 glob ,因此它将根据当前目录的内容构建。cd$DIR