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
,但問題是針對任何命令
在普通 sh 和向後兼容普通 sh 的 shell 中,模式
**
和*
是等價的。Zsh 在幾個方面偏離了 sh 兼容性,其中之一是模式和**/
遞歸globbing。搜尋目前目錄、其子目錄、其子子目錄等類似,但也遍歷子目錄的符號連結。***/``**/…``***/…
您可以在 bash ≥4.3 中使用 啟用類似功能
shopt -s globstar
,在 ksh93 中使用set -o globstar
/啟用類似功能set -G
。其他相關選項包括:
shopt -s dotglob
使萬用字元模式匹配點文件(類似於zsh 中的set -o dotglob
/globdots
)。
- 設置
GLOBIGNORE
變數 inbash
也會自動啟用該選項¹。- 您可以在 ksh93 中使用
FIGNORE=.:..
.- 在 zsh 中,這也可以在模式後使用 glob 限定符逐個完成
(D)
。Bash / ksh93 沒有類似的功能。
shopt -s extglob
啟用 ksh88 風格的擴展 glob 運算符(類似於set -o kshglob
zsh 中)(在 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 nullglob
zsh)。
- 在 zsh 中,這可以
(N)
在模式之後使用 glob 限定符逐個完成。在 ksh93 中,放在~(N)
模式之前。Bash 沒有類似的功能。
shopt -s failglob
如果沒有文件匹配,則觸發錯誤,而不是保持模式不變(zsh 中的預設行為)。
set -o globstarshort
inzsh
使**
行為像**/*
. 例如,你**/*.py
也可以寫成**.py
. 在bash -O globstar
,**
only 類似於**/*
(除了dir/**
包含dir/
在其擴展中),但**.py
與 相同*.py
。bash 4.0 引入了
globstar
選項和**
模式,但是要注意,在 bash 4.3 之前,它總是遍歷目錄的符號連結,而在 5.0 之前,它會遍歷一些符號連結。Bash 3.x 及以下版本沒有這樣的功能。和shell
tcsh
中也提供了類似形式的遞歸萬用字元(預設情況下未啟用)。yash``fish
.
¹ 請注意,當涉及到和..
特殊目錄時,這些 shell 之間存在一些差異。它們永遠不會被 glob 擴展zsh
,設置FIGNORE=.:..
在 ksh93 中將它們排除在外,但在 bash 中,它們被排除在諸如*
even with之類的 glob 之外dotglob
,而不是.*
那些。設置GLOBIGNORE=.:..
對 有幫助.*
,但對dir/.*
or沒有幫助.*/file
。