名前が 2 つのパターンと一致する Bash ですべてのファイルを開くまたは一覧表示する方法

名前が 2 つのパターンと一致する Bash ですべてのファイルを開くまたは一覧表示する方法

何千ものファイルがあるディレクトリがあるとしましょう。名前に「red」と「green」という文字列の両方を含むすべてのファイルを開く方法は?

答え1

find . -type f -name '*red*' -name '*green*'  -exec echo {} +

または、ファイルを開くために使用したいコマンドechoに置き換えます。vigvimless

一部のプログラムはコマンドラインで複数のファイル名を処理できません。選択したプログラムがこれらのいずれかである場合は、+行末をに置き換えます\;。これにより、長いファイル名のリストに対して一度だけ実行されるのではなく、各ファイル名に対して一度だけコマンドが実行されます。

xdg-openそれが順番です。開くように要求されたファイル形式を検出し、システムの基本プログラム(または基本プログラムをオーバーライドした場合は優先するプログラム)を使用してファイルを開きます。ファイルの種類が認識されない場合は、ファイルを開くときに何を使うべきかを尋ねます。

このように使用するのはfind便利ですが、同時に迷惑なことでもあります。試してみると、その理由がわかります(一致するファイル名に対して1つずつ順番に多くのウィンドウが開くことがわかります)。

find . -type f -name '*red*' -name '*green*' -exec xdg-open {} \;

しかし、一致するファイルを探したい場合*red* または *green*-aの場合、括弧を使用して "and"() および "or"( -o) 演算子の優先順位を指定する必要があります。ただしfind、上記で複数の述語を使用して実行する場合、デフォルトの演算子はaです-a。つまり、述語は論理積で論理的に結合されます。

括弧はシェルで特別な意味を持つため、シェルで解釈されずに find コマンドに渡されるようにバックスラッシュでエスケープする必要があります。

find . -type f \( -name '*red*' -o -name '*green*' \) -exec echo {} +

これを「一般ファイル AND ('*red*' または '*green*' と一致するファイル名)」として読み込みます。

答え2

そしてzsh

set -o extendedglob # best in ~/.zshrc
ls -ld -- *green*~^*red*

glob~演算子は次の目的で使用されます。とは別にまさか)。^あるいいえ。だから組み合わせはいいえだから、そして。 IOW、greenファイル名のファイルと一致します。とは別にする人いいえ含むred

否定演算子を使用する代替^(必須extendedglob):

ls -ld -- ^(^*green*|^*red*)

緑を含まない、または赤を含まないファイルを除くすべて。

隠しファイルを含めるには、(D)glob修飾子を追加してください。

glob修飾子を使用してファイル名を正規表現と一致させることもできます。これにより、setopt rematchpcreこれらの正規表現PCREを作成できます。そして:

re() {
  setopt localoptions rematchpcre
  [[ $REPLY =~ $1 ]]
}
ls -ld -- *(e['re "^(?=.*green).*red"'])

または:

re() {
  setopt localoptions rematchpcre
  [[ $REPLY =~ $RE ]]
}
RE='^(?=.*green).*red'; ls -ld -- *(+re)

(PCREは非テキスト文字列をブロックし、すべてのマルチバイトテキストエンコーディングをサポートしていません。)

そしてkshまたはbash -O extglobzsh -o kshglob

ls -ld -- !(!(*green*)|!(*red*))

!(pattern)拡張グローバル演算子と同じですkshzsh^pattern

次のようにすることもできます。

ls -ld -- @(*green*red*|*red*green*)

ただし、これはどのモデルでも一般化されません。たとえば、abcandを含むファイルの場合、ファイルの一致を実行するには...bcdが必要です。@(*abc*bcd*|*abcd*|*bcd*abc*)???*x*@(x??|?x?|??x)

そしてksh93

ksh93いくつかありますそしてワイルドカード演算子:

ls -ld -- @(*green*&*red*)

またはそれを使用改善正規表現(glob演算子として導入~(A:...)):

ls -ld -- ~(A:.*green.*&.*red.*)

perl-like以下で予測演算子を使用することもできますksh93

ls -ld -- ~(P:(?=.*green).*red.*)

答え3

(ファイルを探しているとします。名前含む両方文字列「赤」そして文字列「緑」)

=~正規表現一致演算子を使用してファイル名の「赤」と「緑」をテストするために bash を無意味に使用するには、次のようにします.

for f in *
do
  [[ $f =~ red && $f =~ green ]] && echo Bash: yes: "$f" || echo Bash: no: "$f"
done

標準シェル構文を使用するには、caseglobを使用して同じファイルを見つけます。

for f in *
do 
  case "$f" in
    *green*red*|*red*green*) echo Case: yes: $f;; 
    *) echo Case: no: $f;; 
  esac
done

より簡単には、シェルワイルドカードを使用することです。

printf "Glob: %s\n" *green*red* *red*green*

実行例:

$ touch a b aredgreenb agreenredb agreenbred aredbgreen red green redgreen greenred

$ for f in *
>     do
>       [[ $f =~ red && $f =~ green ]] && echo Bash: yes: "$f" || echo Bash: no: "$f"
>     done
Bash: no: a
Bash: yes: agreenbred
Bash: yes: agreenredb
Bash: yes: aredbgreen
Bash: yes: aredgreenb
Bash: no: b
Bash: no: green
Bash: yes: greenred
Bash: no: red
Bash: yes: redgreen


$ for f in *
>     do
>       case "$f" in
>         *green*red*|*red*green*) echo Case: yes: $f;;
>         *) echo Case: no: $f;;
>       esac
>     done
Case: no: a
Case: yes: agreenbred
Case: yes: agreenredb
Case: yes: aredbgreen
Case: yes: aredgreenb
Case: no: b
Case: no: green
Case: yes: greenred
Case: no: red
Case: yes: redgreen

$ printf "Glob: %s\n" *green*red* *red*green*
Glob: agreenbred
Glob: agreenredb
Glob: greenred
Glob: aredbgreen
Glob: aredgreenb
Glob: redgreen

答え4

openコマンドが複数の引数を処理できると仮定すると簡単です。

open *red* *green*

編集:申し訳ありません。質問を(名前が赤のファイル)と(名前が緑のファイル)として読み込んでいました。

以下はextglobを使用し、名前が次のファイルの場合は二重計算を防ぎますredgreenred

$ shopt -s extglob     # turn on extended globbing
$ printf "extglob: %s\n" @(*green*red*|*red*green*)
extglob: agreenbred
extglob: agreenredb
extglob: aredbgreen
extglob: aredgreenb
extglob: greenred
extglob: redgreen
extglob: redgreenred
$ shopt -u extglob     # turn off extended globbing

関連情報