我有这个文件树:
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 kshglob
zsh)(在 ksh 中始终启用)。- zsh 还提供了
set -o extendedglob
一种用不同语法表达任意正则表达式(使用否定运算符)的替代方法。 Bash 没有与该语法等效的语法。
- zsh 还提供了
shopt -s nocaseglob
使模式匹配不区分大小写(类似于zsh 中的set -o nocaseglob
/set +o caseglob
)。- 在 zsh 中,这可以根据具体情况通过在模式前加上
(#i)
.同样,在 ksh93 中,您可以为模式添加前缀~(i)
. Bash 没有类似的功能。
- 在 zsh 中,这可以根据具体情况通过在模式前加上
shopt -s nullglob
如果没有文件匹配,则将 glob 模式扩展为空列表,而不是保持模式不变(类似于set -o nullglob
zsh)。- 在 zsh 中,这可以根据具体情况使用
(N)
模式后面的 glob 限定符来完成。在 ksh93 中,放在~(N)
模式之前。 Bash 没有类似的功能。
- 在 zsh 中,这可以根据具体情况使用
shopt -s failglob
如果没有文件匹配则触发错误,而不是保持模式不变(zsh 中的默认行为)。set -o globstarshort
inzsh
使**
行为像**/*
.例如,您**/*.py
也可以写成**.py
.在 中bash -O globstar
,**
单独类似于**/*
(除了dir/**
包含dir/
在其扩展中),但**.py
与 相同*.py
。
Bash 4.0 引入了该globstar
选项和**
模式,但是要注意,在 bash 4.3 之前,它总是遍历目录的符号链接,而在 5.0 之前则遍历一些符号链接。 Bash 3.x 及以下版本没有这样的功能。
类似形式的递归通配符也可在tcsh
、yash
和fish
shell 中使用(默认情况下未启用)。
¹ 请注意,当涉及到.
和..
特殊目录时,这些 shell 之间存在一些差异。它们永远不会被zsh
glob 扩展,设置FIGNORE=.:..
在 ksh93 中将它们排除,但在 bash 中它们被排除在 glob 之外,例如*
Even with dotglob
,但不从 the 中排除.*
。设置GLOBIGNORE=.:..
有助于.*
,但对dir/.*
或没有帮助.*/file
。