强制 Bash 4 'globstar' 选项忽略符号链接

Kyl*_*and 7 bash zsh symlink glob

Bash 4 有一个很棒的选项,称为“globstar”,它模拟(即从)zsh 的**语法来跨多个目录进行通配符。但是,由于它始终遵循符号链接,因此它有点瘫痪(至少对于我的使用而言)。

有没有办法防止**跟随符号链接?如果没有,是否有计划在未来版本中将此功能添加到 Bash?在那之前(或者如果没有这样的计划),任何人都可以提出一个体面(和方便)的解决方法吗?

我想我已经读过 zsh 的实现更灵活并且没有这个问题,但不幸的是我不能只切换到 zsh,因为我们在我的工作场所获取了很多 bash 脚本,我没有时间或将它们全部转换为 zsh 并保持最新状态的诀窍。(我想可能可以启动 Bash 子shell,获取所需的脚本,然后以某种方式将所有更改的环境变量、别名、函数等反向移植到 zsh 中,但我也不知道该怎么做。)

我知道我可以使用find它来编写一个函数,它会按照我想要的方式运行,然后**为这个函数设置别名,但是我无法做类似的事情path/to/parent/**/child/paths并让它正常工作;我能得到的最接近的是类似$(** path/to/parent child/paths), where**是一个函数的别名,该函数将父路径作为第一个参数,然后--wholename */child/paths/*作为参数包含在find它构造和执行的命令中。这既尴尬又丑陋,我真的想要更好的东西。(特别是,我喜欢这种path/**/path格式很容易允许变化,path/**而且**/path很容易直观,而函数会将其分别转换为** path/** '.' /path,其中第二个非常糟糕。)

有什么想法吗?

Evg*_*gin 5

**不遵循符号链接,因为bash-4.3.

请参阅和之间的变化bash-4.3-releasebash-4.3-rc2

globstar (**) 不再遍历解析为目录的符号链接。这消除了一些重复的条目。


Gil*_*il' 3

没有办法阻止**bash 中的符号链接,也没有请求提供方法

\n\n

如果您想编写代码,您可以修补 bash 以引入一个新选项,用于关闭符号链接遍历**。如果您将补丁提交给 bash 维护者,这将增加该功能有一天出现的机会。尽管如此,至少在此期间,您最终不得不部署和维护关键系统程序的本地版本,这可能是一个坏主意。

\n\n

没有办法改变**别名的行为。如果您使用中间数组来存储扩展的结果,则可以使用以下方法find

\n\n
find . \xe2\x80\xa6 -print0 | {\n  a=()\n  while read -r -d "" line; do \n    a+=("$line")\n  done\n  frobnicate "${a[@]}"\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

请注意,程序的整个部分使用了输出find必须位于管道的右侧,因为 bash 在子进程中执行管道的右侧。

\n\n

如果可以排除名称包含换行符的文件,则更容易:

\n\n
set -f; IFS=\na=($(find . \xe2\x80\xa6 ! -name $\'*\\n*\' -print))\nset +f; unset IFS\nfrobnicate "${a[@]}"\n
Run Code Online (Sandbox Code Playgroud)\n\n

您可以尝试在 zsh 的 ksh 模拟模式下运行现有脚本。Zsh 并未实现 bash 的所有功能 \xe2\x80\x94\xc2\xa0 几乎所有 bash 的功能都存在于 zsh 中,但有时语法不兼容。您还可以尝试使用 ksh93 运行脚本:自 93o+ 支持以来的版本**(如 zsh),并且大多数(但不是全部)bash 功能都来自 ksh,因此您的脚本可能很容易移植到 ksh93。切换到 ksh 还有一个额外的好处,那就是它往往比 bash 或 zsh 更快。

\n