複数のファイルを削除する検索コマンドはより効率的ですか?

複数のファイルを削除する検索コマンドはより効率的ですか?

複数のサブディレクトリに多数のファイルが含まれているディレクトリから古いファイルを削除したいと思います。

私は次のアプローチを使用しようとしています。インターネット検索の後、これが推奨され効果的なアプローチであるようです。

find . -mindepth 2 -mtime +5 -print -delete

私の期待は、これが基準を満たすファイル(5日以上前に修正され、最小深度基準を満たしている)を印刷して削除し、次のファイルに移動することです。

ただし、このコマンドを実行すると、クエリのメモリ使用量が増加することがわかりますが、何も印刷されません(したがって、まだ削除されていないと仮定します)。これはfind、基準に合ったすべてのファイルを最初に収集し、ファイルシステムツリー全体を巡回してからファイルを印刷して削除することを意味します。

テストを実行した直後にファイルを削除する方法はありますか?これは段階的なクリーンアップに役立ちます。コマンドを終了して後で再実行することを選択できます(これにより、ファイルの削除が効果的に戻ります)。現時点では、findが巨大なファイルシステムツリーのナビゲーションを完了するまで何も削除しないので、これは起こらないようです。この問題を解決する方法はありますか?

編集 - マイユースケースのリクエストデータを含めます。

クリーンアップしたいディレクトリの最大深さは約4です。通常のファイルはファイルシステムの葉にのみ存在します。約6億の一般的なファイルがあり、リーフディレクトリには最大5つのファイルが含まれています。下位レベルのディレクトリのファンアウトは約3つです。上層部のファンアウトはすごいです。単一の7.2TB LVMディスクが占める総容量は6.5TB(4〜2TBの物理HDDを含む)です。

ベストアンサー1

findコマンドが遅い理由

それは本当に興味深い質問...または正直、悪意のある:

注文する

find . -mindepth 2 -mtime +5 -print -delete

一般的な試用版とは非常に異なる危険な部分は省略されています-delete

find . -mindepth 2 -mtime +5 -print

最も残念な部分はアクションです-delete ヒントオプション-depth。削除を含むコマンドは実際には

find . -depth -mindepth 2 -mtime +5 -print -delete

そしてテストを受けなければならない

find . -depth -mindepth 2 -mtime +5 -print

-depthこれは、オプションが変化する症状と密接に関連しています。ツリー巡回ファイルシステムツリーアルゴリズム予約購入済み深さ優先検索順番に奥行き優先ナビゲーション
以前は、到着したすべてのファイルまたはディレクトリがすぐに使用され、忘れていました。求めるのは、木自体を使って道を見つけることです。findまだ見つからないファイルやディレクトリを含む可能性のあるすべてのディレクトリを削除する前に収集する必要があります。最も深いディレクトリから。これを行うには、巡回フェーズを計画して記憶する独自のタスクを実行する必要があり、ポイントは次のとおりです。ファイルシステムツリーが自然にサポートする順序とは異なる順序で実行する必要があります。したがって、実際には、出力の最初のステップが機能する前に、複数のファイルからデータを収集する必要があります。

Findは後でアクセスできるように一部のディレクトリを追跡する必要があります。これは一部のディレクトリでは問題ではありません。
ただし、おそらくさまざまなレベルのディレクトリに多くのディレクトリがある可能性があります。
また、この場合、find以外のパフォーマンスの問題が明らかになるため、find速度は遅くはありませんが、他のものかもしれません。

パフォーマンスとメモリへの影響は、ディレクトリ構造などによって異なります。


関連の章は以下で提供されます。man find:

「警告」を参照してください。

ACTIONS
    -delete
           Delete  files;  true if removal succeeded.  If the removal failed,
           an error message is issued.  If -delete fails, find's exit  status
           will  be nonzero (when it eventually exits).  Use of -delete auto‐
           matically turns on the -depth option.

           Warnings: Don't forget that the find command line is evaluated  as
           an  expression,  so  putting  -delete  first will make find try to
           delete everything below the starting points you  specified.   When
           testing  a  find  command  line  that you later intend to use with
           -delete, you should explicitly specify -depth in  order  to  avoid
           later  surprises.  Because -delete implies -depth, you cannot use‐
           fully use -prune and -delete together.
    [ ... ]

そして上記のセクションから始めます。

 OPTIONS
    [ ... ]
    -depth Process each directory's contents  before  the  directory  itself.
           The -delete action also implies -depth.


ファイルを削除するための高速ソリューション

実際、ファイルを削除しながらディレクトリも一緒に削除する必要はないでしょうか?ディレクトリを削除しないと、ファイル-depth全体が必要なくなり、ファイルを1つだけ見つけて削除し、提案したように次の手順に進みます。

今回は、単純な印刷バリアントを使用してfind暗黙的にテストできます-print

シンボリックリンク、ディレクトリ、特殊ファイルなどではなく、通常のファイルのみを探しています。

find . -mindepth 2 -mtime +5 -type f

通常、xargs開始されたプロセスごとに複数のファイルを削除し、rm奇妙なファイル名を処理するために、nullバイトを区切り文字として使用します。

このコマンドをテストします。echo上記を参照rmして、後で実行する内容を印刷してください。

find . -mindepth 2 -mtime +5 -type f -print0 | xargs -0 echo rm

この行は長くて読みにくいです。初期テストでは、-n 31行に3つのファイルのみを最初の引数として追加して、読みやすい出力を取得するのに役立ちます。xargs

すべてがうまくいったら、echo古いものを削除してrmやり直してください。

そうです。はるかに早く;


何百万ものファイルについて話している場合(あなたが書いたファイルの総数は6億です)、考慮すべき事項があります。

ほとんどのプログラム(含むfind)はライブラリ呼び出しを使用してディレクトリを読み込みます。readdir (3)。 32KB バッファは通常、ディレクトリを読み取るために使用されます。これは、ディレクトリが大きく、潜在的に長いファイル名の巨大なリストを含む場合に問題になる可能性があります。

この問題に対する解決策は、システムコールを直接使用してディレクトリエントリを読み取ることです。 getdents (2)、より適切な方法でバッファリングを処理します。

もっと800万のファイルを含むディレクトリを一覧表示できます。しかし、lsを使用しない..


(ディレクトリあたりの一般的なファイル数、ディレクトリあたりのディレクトリ数、最大パスの深さ、使用されるファイルシステムに関する詳細を質問に追加できる場合は興味深いでしょう。)

(それでも速度が遅い場合は、ファイルシステムのパフォーマンスの問題を確認する必要があります。)

おすすめ記事