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 を使用し、その 1 つの glob がどのファイルにも一致しなかった場合にのみコマンドをキャンセルします。
ls -d ./foldername/*.(a|b|)test
は使用したくないでしょう。なぜなら、どのグロブも一致しない場合は引数なしでnullglob
実行されるため、現在のディレクトリを一覧表示します。はその点で優れています。これは、一致しないグロブを削除しますが、すべてのグロブが一致しない場合はコマンドをキャンセルします。ls
cshnullglob
nonomatch
を使用すると、 の動作が壊れてしまいbash
、残念なことになるので、は使用したくないでしょう。
zsh
との両方で機能する glob の代替としてbash
、 ksh glob (set -o kshglob
および)zsh
を使用できます。shopt -s extglob
bash
次に、次のようにします。
ls -d ./foldername/*.@(a|b|)test
または:
ls -d ./foldername/*.?([ab])test
一致しない場合に glob が文字通り渡されるのを回避するには、failglob
オプションを追加します。bash
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 を実行するシェル関数を使用してこれをエミュレートすることもできますが、C で記述すると実行がはるかに速くなります。
ls のハッキングについては、私の個人 wiki にまとめました。http://linux.chalisque.net/LsIgnoreMissing
答え4
@DopeGhoti からのコメントが私には効果がありました。
つまり、次のようにエラーを/dev/null
using2>
演算子にリダイレクトします。
ls ./foldername/*.{a,b,}test 2> /dev/null