ターミナルから1つのファイルを除く特定の拡張子を持つファイルを削除する


36

「filename.gif」という名前の1つのファイルを除き、拡張子が.gifのファイルをすべて削除する必要があります。ターミナルでこれを行う最適な方法は何ですか?

コマンドrm *.gifは、ファイルを含むすべてのgifファイルを削除しますfilename.gif

回答:


66

おそらく使用すべきシンプルなソリューションは次のとおりです。

mv filename.gif filename.gif.keep
rm *.gif
mv filename.gif.keep filename.gif

.keep拡張子について特別なことはありません.gif。これにより、一時的にファイル名がで終わらないようになります。

ファイルの名前を変更してはいけない場合(およびこれが重要なスクリプトの状況がある場合):

for X in *.gif; do
    if [ "$X" != "filename.gif" ]; then
        rm "$X"
    fi
done

または、次のように短く書くことができます。

for X in *.gif; do [ "$X" != "filename.gif" ] && rm "$X"; done

find代わりに使用することをお勧めします。それは非常に強力であり、あなたそれをより読みやすくすると思うかもしれません、そして、それらのような文字を持つ奇妙なファイル名を*より良く処理します

find . -maxdepth 1 -not -name 'filename.gif' -name '*.gif' -delete

-not読みやすさのために演算子を使用しましたが、POSIX準拠が重要な場合-GNU findを使用していない場合、またはこれが他の人に再配布したり、さまざまなシステムで実行するスクリプト用である場合-する必要があります!代わりに演算子を使用します。

find . -maxdepth 1 ! -name 'filename.gif' -name '*.gif' -delete

便利なことの1つfindは、大文字と小文字を区別しないようにコマンドを簡単に変更して、次のような拡張子を持つファイルを見つけて削除できる.GIFことです。

find . -maxdepth 1 -not -name 'filename.gif' -iname '*.gif' -delete

私が使用したことに注意してください-inameの代わりに、-name検索パターンのための*.gifが、私はしているではないためにそれを使用filename.gif。おそらくあなたはあなたのファイルが何と呼ばれているかを正確に知って-inameおり、拡張子だけでなくファイル名のどこでも代替大文字と一致します。

これらのソリューションすべて、現在のディレクトリにすぐに存在するファイルのみを削除します。現在のディレクトリに含まれていないファイルは削除しません。また、現在のディレクトリのサブディレクトリにあるファイルも削除しません。

あなたはどこでも、現在のディレクトリに含まれるファイルの削除したい場合は- 、使用(など、あるサブディレクトリを含め、それらのサブディレクトリのサブディレクトリに、ファイルが現在のディレクトリまたはその子孫のいずれかの内に含まれる)find なし maxdepth -1

find . -not -name 'filename.gif' -name '*.gif' -delete

これに注意してください!

を使用して他の値を設定することもできます-maxdepth。たとえば、現在のディレクトリとその子と孫のファイルを削除し、それよりも深くないファイルを削除するには:

find . -maxdepth 3 -not -name 'filename.gif' -name '*.gif' -delete

-delete他の表現の前に、決して最初に置かないでください!あなたは私がいつも-delete最後に置いているのを見るでしょう。最初に配置すると、最初に評価され、下にあるすべてのファイル.(末尾がでない.gifファイルやの深いサブサブサブディレクトリ内のファイルを含む.)が削除されます!

詳細については、のマニュアルページを参照bashしてsh、これらの例で使用するコマンドのを:mvrm[、及び(特に)find


1
ありがとう、エリア。私があなたが提案した最初の方法、つまりファイルを別の形式に変換し、それを元に戻す方法と同じようにしました。しかし、それは少し最適ではなく、汚れているように見えました。私はあなたと@efthialexが提案した2番目のアプローチが好きで、今それを使っています。ありがとう!

1
@Marvisこれがあなたのニーズを満たしてくれて嬉しいです。ところで、私findは非常に汎用性の高いを使用して、別のメソッド(またはメソッドのクラス)に関する情報でこの答えを拡張しました。
エリアケイガン

3
詳細な回答をありがとう、find確かに良い発見です。

1
常識(move-delete-move)の回答に対して+1。
モニカドールを復活させる

Nit-pick:for-loopよりもfind奇妙なファイル名をどのように扱うの*ですか?forループは*、二重引用符を使用したため、ファイルを正常に処理します。
フリム

28

あなたが使用している場合bash(デフォルトシェル)、extglobシェルオプションでは、拡張されたパターンマッチング構文を使用することができます。有効にするには、shopt組み込みコマンドを使用します。

shopt -s extglob

.bashrcファイルにその行を含めます。)

特に、!()演算子へのアクセスを許可します。これは、括弧内にないパターンに一致します。あなたの目的のために:

rm !(filename).gif

詳細については、man bash「パターンマッチング」を参照してください。


1
素晴らしい答えです!これはbash固有であるため、ポータブルスクリプトには適していませんが、インタラクティブなタスクや一部のスクリプトにさえ適しています。extglob有効にする必要がある追加の複雑さがありますが、無効にした場合、悪いことは何も起こりません(その場合、これは機能しません)。そしてshopt -s extglob、私は自分の(またはグローバルな)設定ファイルのどれも持っていなくても、デフォルトで有効になっているようです。そのまま使用できる理由について簡単な説明がある場合は、この回答に追加してください。または、新しい質問を投稿できます。
エリアケイガン

13

+ +でターミナルを開き、次を入力します。CtrlAltT

find . -type f -name "*.gif" -and -not -name "filename.gif" -exec rm -vf {} \;

違い-deleteとは、-exec rm -vf {} \;二番目のオプションで、あなたが原因で、ファイルが削除されているかを確認することができるということである-vフラグ。それは-deleteオプションではできません。(-name -deleteファイル名を印刷しますが、各ファイルが正常に削除されたかどうかrm-v明らかにます。)


1

GLOBIGNORE変数があります。からman bash

GLOBIGNORE
      A colon-separated list of patterns defining the set of filenames
      to be ignored by pathname expansion.  If a filename matched by a
      pathname expansion pattern also matches one of the  patterns  in
      GLOBIGNORE, it is removed from the list of matches.

したがって、簡単な方法はGLOBGINORE、問題のファイル名に設定するだけです。

$ touch {a,b,c,d}.png
$ echo *.png
a.png b.png c.png d.png
$ GLOBIGNORE=c.png
$ echo *.png
a.png b.png d.png

だから、あなたの場合:

GLOBIGNORE=filename.gif; rm *.gif

もちろん、GLOBIGNOREパターンが含まれているため、パターンを除外したいときにいつでも使用できます。

$ GLOBIGNORE='[a-c].png'; echo *.png
d.png
$ touch bd.png; GLOBIGNORE='?.png'; echo *.png
bd.png

の利点(?!)GLOBIGNOREを設定すると、自動的に除外.および..一致から除外され、次のことが可能になりますdotglob

The  GLOBIGNORE shell variable may be used to restrict the set of file‐
names matching a pattern.  If GLOBIGNORE is set, each matching filename
that also matches one of the patterns in GLOBIGNORE is removed from the
list of matches.  The filenames ``.''  and ``..''  are  always  ignored
when  GLOBIGNORE is set and not null.  However, setting GLOBIGNORE to a
non-null value has the effect of enabling the dotglob shell option,  so
all other filenames beginning with a ``.''  will match.  To get the old
behavior of ignoring filenames beginning with a ``.'', make ``.*''  one
of  the  patterns  in  GLOBIGNORE.  The dotglob option is disabled when
GLOBIGNORE is unset.

したがって、ディレクトリ内のすべてのファイルとフォルダを削除する簡単な方法:

GLOBIGNORE=.; rm -r *

*始まるファイル名と一致します.から、GLOBIGNORE有効になってdotglob、それが一致しません.または..あなたが道その親ディレクトリには影響しませんので、。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.