web-dev-qa-db-ja.com

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

何百万ものgif画像でディレクトリを埋め尽くしました。 rmコマンドには多すぎます。

私はこのようなfindコマンドを試してきました:

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

問題は、それが私のマシンを本当に悪い状態に陥らせ、サーバーであるために顧客にタイムアウトを引き起こすことです。

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

38
Corepuncher

速くすることは必ずしもあなたが望むものではありません。 slowerを実際に実行して、実行中に削除されるリソースが少なくなるようにすることができます。

コマンドの優先順位を下げるには、 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
45
John Kugelman

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

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

元のコマンドと比較すると、xargsへのパイプを回避することで、CPUサイクルをさらに節約できる可能性があります。

22
user2719058

番号。

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

[〜#〜] cpu [〜#〜]リソースをスケジュールするため、Nice(または実行中のプロセスではrenice)を使用しても部分的にしか効果がありません。ディスクではありません!また、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秒待機します。それははるかに長くかかりますが、あなたの顧客は遅延に気付くべきではありません。

14
Tomas

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

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

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

システムや状況によっては実際的ではないかもしれませんが、これが適切な方法である明らかなケースを想像するのは簡単です。

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

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

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

5
Kaz

やってみました:

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

最後に+記号を付けると、単一のrmコマンドを実行するために、findにより多くのファイルが含まれます。詳細は この質問 を確認してください。

4
Bartosz Firyn