bash - 扩展的 glob 没有按预期扩展

标签 bash glob

我有一个名为 except.sh 的 bash 脚本,它传递了一个文件/目录列表,如下所示:

$ ls
a b c d/
$ ./except.sh b c

当调用 except 这种方式时,它应该扩展为 a d/ 即除给定名称之外的所有文件/目录。

下面是我尝试实现的方法:

#!/usr/bin/env bash

# enable extended globbing
shopt -s extglob

# set IFS to | so that $* expands correctly
IFS='|'

printf '%s' !("$*")

给定 b c 作为参数,最后一行应该展开为

printf '%s' !(b|c)

导致 a d 被打印。但令我惊讶的是,

abcd

被打印出来。我做错了什么?

最佳答案

问题是$*是在双引号里的,这意味着它的内容不会被当作一个模式,就像echo "*"不会展开一样星号。将外部模式与内部引用部分组合会自动转义后者,因此 !("b|c") 被视为 !(b\|c)。对不存在的 b|c 文件的否定自然会扩展到目录中的所有文件。

另一个问题是扩展的 globbing 被设置为 |IFS 弄乱了,所以你必须在扩展模式之前重置它。因此,必须分两步进行扩展:首先计算模式,然后重置IFS并扩展它:

#!/usr/bin/env bash

# enable extended globbing
shopt -s extglob

# temporarily set IFS to | so that $* expands to part an extended pattern
old_ifs=$IFS
IFS='|'
pattern="!($*)"
IFS=$old_ifs

printf '%s' $pattern

关于bash - 扩展的 glob 没有按预期扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14197202/

相关文章:

bash - 如何递归地计算目录中的所有代码行?

bash - expr 中的 shell float

regex - 从字符串中切出一段并返回相反的部分

ruby - 如何测试字符串是否与 Ruby 中的 glob 匹配?

python - 排除 glob.glob() 中的文件

java - 如何在.bash_profile 中设置JAVA_TOOL_OPTIONS?

linux - 文件名匹配,区分数字和字符

python - 用填充的 0 来通配一个范围 - python

c - 从当前目录获取文件名,保存到 char ** array, glob, C, seg fault

bash - 使用命令行从指定路径递归删除node_modules文件夹