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
,其中第二个非常糟糕。)
有什么想法吗?
没有办法阻止**
bash 中的符号链接,也没有请求提供方法。
如果您想编写代码,您可以修补 bash 以引入一个新选项,用于关闭符号链接遍历**
。如果您将补丁提交给 bash 维护者,这将增加该功能有一天出现的机会。尽管如此,至少在此期间,您最终不得不部署和维护关键系统程序的本地版本,这可能是一个坏主意。
没有办法改变**
别名的行为。如果您使用中间数组来存储扩展的结果,则可以使用以下方法find
:
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\nset -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 更快。