数百万のファイルを削除する


38

数百万のgif画像でいっぱいになったディレクトリがありました。rmコマンドには多すぎます。

私はこのような検索コマンドを試しています:

find . -name "*.gif" -print0 | xargs -0 rm

問題は、マシンが本当に悪い状態に陥り、サーバーであるために顧客にタイムアウトが発生することです。

マシンをロックせずに、これらのファイルをすべて削除するより速い方法はありますか?


以下の「素敵な検索」コマンドを使用して、約6ギガバイト/時間の削除レートです。すべてのファイルを削除するには48時間かかる可能性があります。これは、b / ca scourスクリプトが失敗したためですrmコマンドで「イベントホライズン」、それは逃げた。

3
dir全体を削除するのはそれほど速くありませんか?残りのファイルを削除する前に「良い」ファイルを取り出して
ください...-tucuxi

さて、/ dir_oldに移動されたため、すべてのファイルは現在不良です。/dirを再作成しました。しかし、rmdirはrm *と同じ制限に遭遇しませんか?

@Corepuncher:私は、ディレクトリ全体を(除去することのようにすることを期待するrm -rfより速いだろうそれの試してみる価値。。
ジェイソン・R

現在、ディレクトリで「rm -rf」を実行しています。現在20分以上稼働しています...ディスクサイズはまだ変更されていません。しかし、まだ「引数リストが長すぎます」も自動的には返されませんでした。唯一の問題は、それは本当に私のマシンを打撃し、他のものを遅く/失敗させることです。どれくらいの時間を手放すかわからない。

回答:


44

速くすることは必ずしもあなたが望むものではありません。実際に実行速度を遅くしたい場合があるので、実行中に削除するリソースが少なくなります。

nice(1)を使用して、コマンドの優先順位を下げます。

nice find . -name "*.gif" -delete

I / Oバウンドプロセスの場合、nice(1)では不十分な場合があります。Linuxスケジューラーは、CPUだけでなくI / Oも考慮しますが、I / Oの優先順位をより細かく制御したい場合があります。

ionice -c 2 -n 7 find . -name "*.gif" -delete

それでうまくいかない場合は、スリープを追加して本当に遅くすることもできます。

find . -name "*.gif" -exec sleep 0.01 \; -delete

3
すごい... .1 sのスリープ状態の数百万のファイル... 864000個のファイルに1日が必要です。
glglgl

7
@glglglわかりました、スマートなお尻。タイムアウトを変更しました。:-P
ジョンクーゲルマンはモニカをサポートします

28
スリープは適切な選択かもしれませんが、ここでのタスクはCPUバウンドではなくIOバウンドなので、niceはしません。代わりにioniceを試すことができます。睡眠が小さすぎる場合は役に立たないことに注意してください。
マッテオイタリア

3
@glglgl:重要なのは、サーバーでサービスの中断を引き起こしたくない場合、ゆっくりと行かなければならないということです。
マッテオイタリア

1
+1のsleep追加-を使用してionice -c 3いるにもかかわらず、サーバーがIOで窒息する問題がありました。(もちろん)ファイルをクリアするのにかかる時間は大幅に増加しますが、アプリケーションを停止するよりも待ちたいのですが…
オラチューベソン

22

Linuxを実行しており、このタスクはおそらくI / Oにバインドされているため、次のコマンドを使用して、コマンドにアイドルI / Oスケジューラの優先順位を付けることをお勧めしますionice(1)

ionice -c3 find . -name '*.gif' -delete

元のコマンドと比較すると、のパイプを使用しないことで、CPUサイクルをさらに節約できxargsます。


@Braiamどういう意味ですか?これはfind ... -exec理にかなっている場所ではありません。

ああ、はい、ごめんなさい。私の悪い。確かに効率的ですか?
Braiam

1
まあ、find(1)ドキュメントはそう主張しています。:)そして、findそれ自体にファイルを削除させるほうが、rmコマンドをフォークするよりも効率的であることは明らかです。

1
私は、実稼働サーバー上の400万のファイルがあるフォルダーでいくつかの推奨バージョンを試しましたが、これはシステムを詰まらせない唯一のバージョンです。ionice -c3IOがアイドル状態のときにprioを下げて実行するようにします。以来ことに注意してください-delete検索するための標準ではありません、あなたは、このコマンドを使用して(それが動作することフィードバックを含む)と同じ操作を行うことができますionice -c 3 find . -name '*.gif' -exec echo {} \; -exec rm {} \;-ゆっくりではあるが重要なプロセスの無iowaits。
クリストファーレーケン

13

いや

簡単な方法はありません。ディスクのソフトフォーマットからのアパートです。ファイルは一度にrm 渡されます(コマンドラインの制限まで、に設定することもできますxargs)。これは、各ファイルでrmを呼び出すよりもはるかに優れています。だから、間違いなく、より速い方法はありません。

使用するnice(またはrenice実行中のプロセスで)のは、ディスクではなくCPUリソースをスケジュールするためです。また、CPU使用率は非常に低くなります。これはLinuxの弱点です。1つのプロセスがディスクを「使い果たす」(つまり、多くのディスクで動作する)と、マシン全体が動かなくなります。リアルタイムで使用するために修正されたカーネルが解決策になる可能性があります。

サーバーで私がすることは、手動で他のプロセスに仕事をさせることです-サーバーを「呼吸」させるために一時停止を含めます:

find . -name "*.gif" > files
split -l 100 files files.
for F in files.* do
    cat $F | xargs rm
    sleep 5 
done

これは、100ファイルごとに5秒待機します。かなり時間がかかりますが、顧客は遅延に気付かないはずです。


シェルはに注文されたときに、-SO「ファイルは、コマンドラインの限界まで(一度にRMに与えられている」rm *、それが拡大し*、ファイル名のすべての行にし、それを渡すrm信じられないほど愚かだそれ?。なぜでしょうシェルワイルドカードを展開しますか?

:-D @Joker_vD、あなたの名前が示すように、あなたは冗談を言っていますか?:-)
トマス

2
@Joker_vD:1970年頃からのUnixの決定との互換性。Windowsはそれをしません。そこで、プログラムはワイルドカードをFindNextFile / FindNextFileに渡すことができるため、結果を1つずつ取得できます。
MSalters

@Tomasこの場合はありません。正直なところ、このような設計には2つの問題がすぐにあります。まず、コマンドラインはゴムではありません。第二に、プログラムはで呼び出された*かどうかを判断できず/*、ユーザーのそのような決定に疑念を抱きます。

1
@Joker_vDワイルドカード拡張を行うシェルには多くの良いことがあります。これはWindowsとは異なりますが、それが単にあなたが慣れているものとは異なるという理由だけで信じられないほど愚かであるという結論に飛び付かないでください。詳細を知りたい場合は、Googleで検索するか、関連するStack Exchangeサイトに質問を投稿してください。これは、このコメント領域にとって大きな脱線です。
ジョンクーゲルマンはモニカをサポートします

5

削除するファイルの数が残されているファイルの数を大幅に上回っている場合、削除するファイルのツリーをたどってすべてのファイルシステムの更新を行うのが最も効率的なアプローチではない可能性があります。(不必要な参照カウントのメモリ管理を行い、1つのステップで不要なものをすべてゴミに変えてから、クリーンアップできる範囲をスイープするのではなく、大きなツリー内のすべてのオブジェクトを参照して参照を削除することに似ています)

つまり、別のボリュームに保持されるツリーの部分を複製します。元のボリュームに新しい空のファイルシステムを再作成します。保持されたファイルを元のパスにコピーして戻します。これは、ガベージコレクションコピーすることに漠然と似ています。

ある程度のダウンタイムが発生しますが、継続的な悪いパフォーマンスとサービスの中断よりも優れている可能性があります。

あなたのシステムや状況では実用的ではないかもしれませんが、これが道である明白なケースを想像するのは簡単です。

たとえば、ファイルシステム内のすべてのファイルを削除たいとします。1つずつ再帰および削除するポイントは何でしょうか?マウントを解除し、パーティションの上部で「mkfs」を実行して空のファイルシステムを作成します。

または、半ダースの重要なファイルを除くすべてのファイルを削除したいとしますか?そこから半ダースを取得し、...「mkfs」の上に。

最終的には、停止する必要のあるファイルが十分にある場合、いくつかの損益分岐点があり、ダウンタイムなどの他のコストを考慮して、再帰的な削除を行う方が安くなります。


4

やってみました:

find . -name "*.gif" -exec rm {} +

末尾の+記号により、findは実行される単一のrmコマンド用のファイルをさらに含みます。詳細については、この質問を確認してください。


-print0よりもはるかに高速に実行されます。xargsソリューション。rmプロセスはすべてのファイルに対してではなく、それらの大規模なセットに対して呼び出されるため、負荷が低くなります。

@JohnKugelman正しいですが、これはGNUの拡張機能であり、ネイティブのfindコマンドで常に使用できるとは限りません。
-CodeGnome

OK、面白いですが、これはまったく新しいものです(同様に-delete)必ずしもそこにある必要はありません
トーマス

しかし、これはOPのソリューションと比べて確かに良いものは何ももたらしません。
トマス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.