`[!]`(括弧内の感嘆符)ワイルドカード


10

私はグロビングパターンとワイルドカードに出くわしましたが、特に興味があるのは[!]です。

この構成は構成と似て[!]いますが、大括弧内の任意の文字と一致するのではなく、[との間にリストされていない限り、任意の文字と一致します]

rm myfile [!192]

上記では、名前に192が含まれているすべて/すべてのファイルを除いて、すべて/すべてのファイルが削除されると思います。

ただし、これをファイル拡張子とともに適切に使用すること、特に複数の条件について心配しています。

そのような状況で適切な構文は何でしょうか?

rm myfile [!.gif .csv. mp3] 

または

rm myfile [!.gif !.csv !.mp3]

私の心配は、ピリオドが誤った場所に置かれる可能性があるため、特定のファイルの操作を引き起こそうとしているときに、(確かにそれらのいずれかでしょうか?)を含むすべてのファイル.が操作されることです。

この構成は構成と似て[ ]いますが、大括弧内の任意の文字と一致するのではなく、[との間にリストされていない限り、任意の文字と一致します]

http://www.tldp.org/LDP/GNU-Linux-Tools-Summary/html/x11655.htmから引用)

今; それから、単数!で十分であり、その中のすべての値が範囲内に含まれていることを示唆している私にとっては。


5
一般的なヒントとして、ls my-patternまたはecho my-commandを使用して、実行前にrm
グロビングが希望どおりに

また、ほとんどではないにしても、多くのファイルには拡張子がないことに注意してください。Linuxシステムの拡張機能は通常無関係であり、ほとんどのプログラムでファイルタイプの定義に使用されません。
terdon 2017年

2
あなたの最初の引用符が誤って引用されていることを注意は、今では基本的にそれが言うように見える[!]ように似ているがない[!]
ilkkachu

2
それは言及する価値だ^とまったく同じ意味を持っている!ので、この文脈での[^a]除外をaまったく同じように[!a]行います。最初の文字は、以下の場合は[です!または^の場合、囲まれていない任意の文字が一致します。man bash
2017年

3
rm myfile [!192]削除されるmyfileだけでなく、任意の単一文字のファイル名前が付けられていない19または2
ケビン

回答:


16

引用man 7 glob

An  expression  "[!...]"  matches  a single character, namely any character
that is not matched by the expression obtained by removing the first '!' from it.
(Thus, "[!]a-]" matches any single character except ']', 'a' and '-'.)

ここでは単一文字の部分を強調しており[]、Bashパターンマッチングでは文字列全体に使用できません。


bashBrace Expansionを使用して文字列を一致させることができますが、それらを否定する方法(私は知っています)はありません。例えば

1.{gif,csv,mp3}

に拡張されます

1.gif 1.csv 1.mp3

これらのファイルが存在するかどうかに関係なく。


wcharginが指摘shoptそれらのいずれかである、拡張パターンマッチング演算子を有効にするために使用することができます!()。実行後shopt -s extglob、例えば

1.!(gif|csv|mp3)

に拡張されます

1.jpg 1.bmp 1.png

それらのファイルが現在のディレクトリに存在する場合。詳細についてはman bash(セクションEXPANSION /パス名展開)およびパス名展開(グロビング)を参照してください


あなたがやろうとしていることについては、私は常にを使用しますfind。これは、たとえば次のように、否定などを提供します。

find . -maxdepth 1 -type f ! -name "*.gif" -a ! -name "*.csv" -a ! -name "*.mp3"

これは結果をリストするだけです。それらを削除したい場合は、コマンドの最後-deleteオプション追加してください。常にアクションを削除する場合と同様に、常に最初に慎重に確認してください

findが非常によく説明しているたくさんの便利なオプションを提供していますman find


1
このfindコマンドは再帰的であることに注意してください(編集:元々表示されていたため、関連する重要ではない追加情報のためにこのコメントを残す場合があります)。現在のディレクトリにのみ存在し、そのサブディレクトリにも存在しないファイルを検索し、-deleteアクションが追加された場合にのみそれらのファイルを削除するには、の-maxdepth 1直後に追加できますfind .globstarシェルオプションがオンになってい**て使用されていない限り、グロブはBashでは再帰的でないため、これはグロビングの効果と一致します。質問に示されているグロブはすべてのシェルで非再帰的です。
Eliah Kagan 2017

2
「それらを否定する方法は、(私の知っている)が存在しない」-with shopt -s extglob、あなたが使用することができecho 1.!(gif|csv|mp3)、すべてが印刷され、1.extどこextではないgifcsvまたはmp3。(の「パターンマッチング」サブセクションを参照してくださいman bash。)
wchargin

10

ブラケットの使い方を誤解していると思います。[abc]一致する1文字のabまたはc[!abc]マッチする1つのである文字ではないが abc。したがって、コマンド

rm myfile [192]

削除されるmyfileと、ファイル19および2あなたがmyfileのとブラケットの間にスペースを持っているので。対照的に、コマンド

rm myfile[192]

ファイルを削除しますmyfile1myfile9myfile2


本当。使用する方が良いfind
pLumo 2017年

実際、[]は範囲に使用され、[!]は1文字
IronUhlan

1
@IronUhlan、どちらも範囲または文字のリストを取ります。それはもう一方が否定であるというだけです。
ilkkachu 2017年

7

大括弧[ ]は文字クラスを示します。それらの中の単一の文字は、与えられた位置で一致するかもしれません。そう

file[192]

3つの可能な名前に一致します。

file1
file2
file9

後に続く1文字のみを処理するため、一致しませfile192file

大括弧で範囲を使用することもできます。[0-9]指定された位置の任意の1桁に一致します。2桁の場合、が必要[0-9][0-9]です。数字の後に大文字が続く場合は、[0-9][A-Z]...

! 否定を示します。

file[!192]

or またはfileを除いた後に単一文字が含まれるファイルに一致します。たとえば、and および(および他の多くの)には一致しますが、2つの余分な文字があるため、には一致しません192file7filesfile% file192

使用例として、findではなくを使用することをお勧めします[!]。それは持っているnotオペレータを。

また、再帰的です。つまり、デフォルトですべてのサブディレクトリに移動します。-maxdepth 1必要な場合は、で現在のディレクトリに制限できます。シェルワイルドカード(グロビング)は非再帰的です(ただし、再帰的グロビングは**有効にできます)。

シンボリックリンクの削除を避けたくない場合は-type d、否定テストに追加して、ディレクトリの削除を回避できます。その提案をしてくれたEliah Kaganに感謝します。

find /path -maxdepth 1 -not \( -type d -or -iname "*.gif" -or -iname "*.csv" -or -iname "*.mp3" \)

必要なものが表示されたら、次のコマンドを使用してコマンドを再度実行できます -delete

find /path -maxdepth 1  -not \( -type d -or -iname "*.gif" -or -iname "*.csv" -or -iname "*.mp3" \) -delete

2
また、一度に複数の範囲を実行することもできると思います。たとえば、16進数は[0-9a-fA-F]
Wilson

@Zanna、はい!私は実際にfindを使用していました:)「not」演算子があることに気づかなかった:)
IronUhlan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.