bash ** 与 zsh ** 不同,我们可以改变 bash 的行为吗?

bash ** 与 zsh ** 不同,我们可以改变 bash 的行为吗?

我有这个文件树:

a.py
b/c.py

在 Bash 中,ls -l **/*.py给出

b/c.py

在 Zsh 中,ls -l **/*.py给出了一个很好的

a.py
b/c.py

有没有办法改变 bash 行为以避免这样做ls *.py **/*.py

PS:我用过ls,但问题是针对任何命令

答案1

在 plain sh 和与 plain sh 向后兼容的 shell 中,模式***是等效的。 Zsh 在几个方面偏离了 sh 兼容性,其中之一是模式**/***/递归通配符**/…搜索当前目录、其子目录、其子子目录等***/…类似,但也会遍历到子目录的符号链接。

您可以在 bash ≥4.3 中启用类似的功能shopt -s globstar,在 ksh93 中带有set -o globstar/ set -G。其他相关选项有:

  • shopt -s dotglob使通配符模式匹配点文件(类似于zsh 中的set -o dotglob/ globdots)。
    • 设置GLOBIGNORE变量bash也会自动启用该选项。
    • 您可以使用 ksh93 实现类似的效果FIGNORE=.:..
    • 在 zsh 中,这也可以根据具体情况使用(D)模式后面的 glob 限定符来完成。 Bash/ksh93没有类似的功能。
  • shopt -s extglob启用 ksh88 风格的扩展 glob 运算符(类似于set -o kshglobzsh)(在 ksh 中始终启用)。
    • zsh 还提供了set -o extendedglob一种用不同语法表达任意正则表达式(使用否定运算符)的替代方法。 Bash 没有与该语法等效的语法。
  • shopt -s nocaseglob使模式匹配不区分大小写(类似于zsh 中的set -o nocaseglob/ set +o caseglob)。
    • 在 zsh 中,这可以根据具体情况通过在模式前加上(#i).同样,在 ksh93 中,您可以为模式添加前缀~(i). Bash 没有类似的功能。
  • shopt -s nullglob如果没有文件匹配,则将 glob 模式扩展为空列表,而不是保持模式不变(类似于set -o nullglobzsh)。
    • 在 zsh 中,这可以根据具体情况使用(N)模式后面的 glob 限定符来完成。在 ksh93 中,放在~(N)模式之前。 Bash 没有类似的功能。
  • shopt -s failglob如果没有文件匹配则触发错误,而不是保持模式不变(zsh 中的默认行为)。
  • set -o globstarshortinzsh使**行为像**/*.例如,您**/*.py也可以写成**.py.在 中bash -O globstar**单独类似于**/*(除了dir/**包含dir/在其扩展中),但**.py与 相同*.py

Bash 4.0 引入了该globstar选项和**模式,但是要注意,在 bash 4.3 之前,它总是遍历目录的符号链接,而在 5.0 之前则遍历一些符号链接。 Bash 3.x 及以下版本没有这样的功能。

类似形式的递归通配符也可在tcshyashfishshell 中使用(默认情况下未启用)。


¹ 请注意,当涉及到...特殊目录时,这些 shell 之间存在一些差异。它们永远不会被zshglob 扩展,设置FIGNORE=.:..在 ksh93 中将它们排除,但在 bash 中它们被排除在 glob 之外,例如*Even with dotglob,但不从 the 中排除.*。设置GLOBIGNORE=.:..有助于.*,但对dir/.*或没有帮助.*/file

相关内容