glob *.{a,b,}test で中括弧展開を使用する場合、zsh からの「一致なし」を無視します

glob *.{a,b,}test で中括弧展開を使用する場合、zsh からの「一致なし」を無視します

foldernameというフォルダー内にある、拡張子がtestatestまたは のファイルをすべて一覧表示したいと思います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 を使用し、その 1 つの glob がどのファイルにも一致しなかった場合にのみコマンドをキャンセルします。

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

は使用したくないでしょう。なぜなら、どのグロブも一致しない場合は引数なしでnullglob実行されるため、現在のディレクトリを一覧表示します。はその点で優れています。これは、一致しないグロブを削除しますが、すべてのグロブが一致しない場合はコマンドをキャンセルします。lscshnullglob

nonomatchを使用すると、 の動作が壊れてしまいbash、残念なことになるので、は使用したくないでしょう。

zshとの両方で機能する glob の代替としてbash、 ksh glob (set -o kshglobおよび)zshを使用できます。shopt -s extglobbash

次に、次のようにします。

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

または:

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

一致しない場合に glob が文字通り渡されるのを回避するには、failglobオプションを追加します。bashls

見る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 を実行するシェル関数を使用してこれをエミュレートすることもできますが、C で記述すると実行がはるかに速くなります。

ls のハッキングについては、私の個人 wiki にまとめました。http://linux.chalisque.net/LsIgnoreMissing

答え4

@DopeGhoti からのコメントが私には効果がありました。

つまり、次のようにエラーを/dev/nullusing2>演算子にリダイレクトします。

ls ./foldername/*.{a,b,}test 2> /dev/null

関連情報