Bash

使用帶有 glob *.{a,b,}test 的大括號擴展時,忽略 zsh 中的“不匹配”

  • February 15, 2022

我想列出一個名為的文件夾foldername中具有副檔名的所有文件testatestbtest

我的第一想法是跑ls ./foldername/*.{a,b,}test

這可以正常工作,除非副檔名沒有任何內容atest,在這種情況下我會收到錯誤消息zsh: no matches found: ./foldername/*.atest

有什麼方法可以簡單地忽略此錯誤並列印確實存在的文件?

我需要這個在 zsh 和 Bash 中工作。

最好這樣做find

find ./foldername -maxdepth 1 -name '*.atest' -o -name '*.btest' -o -name '*.test'

ls -d ./foldername/*.{a,b,}test

{a,b,...}不是 glob 運算符,這是大括號擴展,首先擴展為:

ls -d ./foldername/*.atest ./foldername/*.btest ./foldername/*.test

並且每個 glob 單獨擴展,如果任何 glob 不匹配,則命令將按照您的預期取消zsh(或fish; 在 中bash,您需要failglob獲得類似行為的選項)。

在這裡,您希望使用與所有這些文件匹配的單個 glob,並且僅在該 glob 不匹配任何文件時才取消命令:

ls -d ./foldername/*.(a|b|)test

您不想使用nullglob,就好像沒有匹配的 glob 一樣,它會在ls沒有參數的情況下執行,所以列出目前目錄。cshnullglob在這方面更好,因為它會刪除不匹配的 glob,但如果所有 glob 都不匹配,仍會取消該命令。

您不想使用nonomatch,因為這會給您bash帶來可恥的破壞行為。

對於同時適用於zshand的 glob 替代方案bash,您可以使用 ksh glob(set -o kshglobinzshshopt -s extglobin bash)。

然後,你會這樣做:

ls -d ./foldername/*.@(a|b|)test

或者:

ls -d ./foldername/*.?([ab])test

添加failglob選項bash以避免當 globls不匹配時直接傳遞給它。

請參閱為什麼 nullglob 不是預設值?了解更多資訊。

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