Bash

bash ** 與 zsh ** 不同,我們可以更改 bash 行為嗎?

  • January 7, 2022

我有這個文件樹:

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 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, **only 類似於**/*(除了dir/**包含dir/在其擴展中),但**.py與 相同*.py

bash 4.0 引入了globstar選項和**模式,但是要注意,在 bash 4.3 之前,它總是遍歷目錄的符號連結,而在 5.0 之前,它會遍歷一些符號連結。Bash 3.x 及以下版本沒有這樣的功能。

和shelltcsh中也提供了類似形式的遞歸萬用字元(預設情況下未啟用)。yash``fish


.¹ 請注意,當涉及到和..特殊目錄時,這些 shell 之間存在一些差異。它們永遠不會被 glob 擴展zsh,設置FIGNORE=.:..在 ksh93 中將它們排除在外,但在 bash 中,它們被排除在諸如*even with之類的 glob 之外dotglob,而不是.*那些。設置GLOBIGNORE=.:..對 有幫助.*,但對dir/.*or沒有幫助.*/file

引用自:https://unix.stackexchange.com/questions/685340