ファイル一括削除

ファイル一括削除

ディレクトリとサブディレクトリにあるすべてのtxt、xls、pdfファイルを削除したいと思います。他のすべてを保存したいです。

find . -type f ! -iname '*.xml$,.png$,.jpeg$,.gif$,' -delete

これは完了したようですが、必要な他のファイルは削除されます。他のコンテンツを削除せずにこれを達成するにはどうすればよいですか?

答え1

この方法:

find . -type f -iname '*.xml' -o -iname '*.png'\
       -o -iname '*.jpeg' -o -iname '*.gif' -delete

正規表現を使用することもできます。

find . -type f -iregex '.*\.\(xml\|png\|jpeg\|gif\)$' -delete

答え2

findを使用してこの問題を解決するには、基本的に4つの方法があります。

方法 #1 - 使用-delete

$ find . -type f -iname '*.xml' -o -iname '*.png'\
       -o -iname '*.jpeg' -o -iname '*.gif' -delete

このQ&Aで他の人が述べたように、この方法は最も高速でリソース集約的です。から引用オンライン文書を探す:

10.1.6 `-delete'ジョブの使用


この問題を解決する最も効率的で安全な方法は、「-delete」操作を使用することです。

 find /var/tmp/stuff -mtime +90 -delete

-exec' orこの回避策は、新しいプロセスをフォークし、/ bin / rm 'を使用するオーバーヘッドを完全に回避するため、どの-execdir'操作よりも効率的です。exec' to runまた、通常はxargs' for the same reason. The file deletion is performed from the directory containing the entry to be deleted, so the「-delete」操作よりも効率的であり、「-execdir」操作と同じセキュリティ上の利点があります。

"-delete"操作はBSDシリーズオペレーティングシステムで導入されました。

メモ:このアプローチで覚えておくべきことの1つは、useが-deleteswitchを意味することです-depth。どういう意味ですか?-delete注意しないと、どのようにやけどをするかについての例は次のとおりです。

たとえば、いくつかのファイルをクリーンアップし、.svnサブディレクトリには変更せずに残したいSubversion作業ディレクトリがあるとします。これを行うには、おそらく次のコマンドを使用します。

$ find . -not "(" -name .svn -type d -prune ")" -type f -print
./a.txt

ただし、スイッチが-delete含まれているため、-depth処理する実際のファイルは次のとおりです。

$ find . -not "(" -name .svn -type d -prune ")" -type f -print -depth
./.svn/all-wcprops
./.svn/entries
./.svn/format
./.svn/text-base/a.txt.svn-base
./a.txt

したがって、-delete使用には注意が必要です。

方法 #2 --exec command {} +

$ find . -type f -iname '*.xml' -o -iname '*.png'\
       -o -iname '*.jpeg' -o -iname '*.gif' -exec rm {} \+

このアプローチと比較すると、-deleteこれはおそらくUnix全体のパフォーマンスと移植性の点で次善の策です。記号-exec ... {} +は次のように機能します。

マンページを探します。

-execジョブのこのバリエーションは、選択したファイルで指定されたコマンドを実行しますが、コマンドラインは選択した各ファイル名を最後に追加することによって構成されます。コマンドの総呼び出し数は、一致するファイルの数よりはるかに少なくなります。 。コマンドラインは、xargsがコマンドラインを作成するのとほぼ同じ方法で作成されます。コマンドには「{}」インスタンスが1つだけ許可されます。このコマンドは起動ディレクトリで実行されます。

したがって、実際にはこの方法は同様に機能しますxargsが、find出力にパイピングする手間を省きませんxargs

方法 #3 -xargs

$ find . -type f -iname '*.xml' -o -iname '*.png'\
       -o -iname '*.jpeg' -o -iname '*.gif' -print0 | xargs -0 rm -f

find ... -print0指定された基準に一致するファイルのリストが構成されます。その後、リストはにパイプされますxargs。この-print0スイッチは、各検索結果の間に区切り記号としてASCII NUL文字を配置します。-0スイッチをオンにすると、xargs受信ファイルがASCII NUL文字で区切られていると仮定します。

この方法は方法#1と#2と比較して方法#2と似ていますが、-print0このスイッチがすべてのUnixシステムで普遍的にサポートされているわけではありません。

方法 #4 --exec command {} \;

$ find . -type f -iname '*.xml' -o -iname '*.png'\
       -o -iname '*.jpeg' -o -iname '*.gif' | exec rm -f {} \;

これは、最初の3つの方法に比べてパフォーマンスが最も低いです。文字通りrm見つかった個々のファイルごとにコマンドを呼び出しますfind

セキュリティに関する追加の注意事項

上記の方法を使用する際には明確ではないかもしれないことの1つは、いくつかの方法が他の方法よりも安全であることです。自分でこう言うこともできます。 ..何?ここに例があります。

あなたがルートだとし、次のコマンドを実行してください。

$ find /var/tmp/somedir -type f -exec rm {} \;

/etcあなたも知らないうちに誰かが指すディレクトリを悪意を持って作成しました/var/tmp/somedir。上記のコマンドを実行すると、そのディレクトリ/etcも削除されます。-deleteこの問題は、オプション(方法#1)を除くすべてのファイルを削除する方法で発生します。

長すぎる博士。

ファイルを削除する最も迅速で安全な方法はfindを使用することです-deletexargs -0パフォーマンスは似ていますが、セキュリティは低いです。操作-deleteは完全に移植可能ではありません。最も効率的な移植可能な選択肢がありますが、-exec ... +これは安全ではなく、4.2.12より前のGNU findutilsバージョンではサポートされていません。

引用する

答え3

やや不正確細い答え

参考事項と免責事項:コメントでなければなりません。細い答えしかし、まだコメントすることはできません。

はい「誰かが悪意のあるリンクを作成しました」セキュリティに関する追加の注意事項UnixハードリンクもUnixソフトリンクも完全に正確ではありません。

2つの違いを理解するには、次を参照してください。UnixのハードリンクとシンボリックリンクまたはGoogleで検索してみてください。

ソフトリンク(最も一般的に使用されるタイプ)の場合GNU findBDS find 確かに-L特定のフラグを使用して強制的に従わない限り、シンボリックリンクに従います。 [望むよりman find]

したがって、この例は、次のような場合を除いて問題にならない可能性があります。 findソフトリンクを追跡するには、このフラグを使用します-L。とにかく危険な選択です。

ハードリンクの場合は、findクリックをリンクしてください。その他のファイルただし、ハードリンクは次のとおりです。その他のディレクトリman lnGNUのように「失敗する可能性があります」ln

   -d, -F, --directory
          allow the superuser to attempt to hard link directories (note: will probably
          fail due to system restrictions, even for the superuser)

したがって、最初にディレクトリへのハードリンクを作成することは不可能であり、find従うべき内容もありません。

一部のBDS実装にはlnオプションはありません。-d

関連情報