我想列出foldername
名為 或 . 的test
資料atest
夾中的所有檔案btest
。
我的第一個反應就是跑ls ./foldername/*.{a,b,}test
這工作正常,除非擴展名沒有任何內容atest
,在這種情況下我會收到錯誤zsh: no matches found: ./foldername/*.atest
。
有什麼方法可以簡單地忽略此錯誤並列印確實存在的文件嗎?
我需要它在 zsh 和 Bash 中都能工作。
答案1
在
ls -d ./foldername/*.{a,b,}test
{a,b,...}
不是全域運算符,這是大括號擴展,首先擴展為:
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
這將是一種恥辱。
對於同時適用於 和 的 glob 替代方案zsh
,bash
您可以使用 ksh glob(set -o kshglob
inzsh
和shopt -s extglob
in bash
)。
然後,你會這樣做:
ls -d ./foldername/*.@(a|b|)test
或者:
ls -d ./foldername/*.?([ab])test
新增該failglob
選項bash
以避免 glob 在ls
不匹配時逐字傳遞。
看為什麼 nullglob 不是預設值?了解更多。
答案2
最好這樣做find
:
find ./foldername -maxdepth 1 -name '*.atest' -o -name '*.btest' -o -name '*.test'
答案3
我遇到了這個問題,首先透過破解 ls 本身來解決它。完成後,我意識到我所需要的只是簡單的 C 程式:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
struct stat statbuf;
int i;
for( i=1; i<argc; i++ ) {
if( stat(argv[i],&statbuf) == 0 ) {
printf("%s\n",argv[i]);
}
}
}
所有這一切以及它需要做的就是運行其命令列參數並回顯與有效文件相對應的那些字串(即 stat() 成功的文件)。
當然,我們可以使用同樣簡單的 Python、Perl 甚至運行 stat 的 shell 函數來模擬它,但用 C 編寫它可以使其運行速度更快。
至於 hacking ls,我已經在我的個人 wiki 上進行了運行:http://linux.chalisque.net/LsIgnoreMissing
答案4
@DopeGhoti 的評論對我有用。
即,將錯誤重定向到/dev/null
使用2>
運算符,如下所示:
ls ./foldername/*.{a,b,}test 2> /dev/null