大量のファイルを削除する簡単な方法

大量のファイルを削除する簡単な方法

多数のキャッシュファイルが迅速に生成されるディレクトリがあります。このファイルは小さすぎるため、すべてのinodeを非常に迅速に消費します。

現在、私は12時間より古いすべてのファイルを見つけて削除するために次のコマンドを実行しています。

$ find ./cache -mtime +0.5 -exec rm {} \;

ただし、このコマンドはファイル生成よりも削除が遅くなります。大量のファイルをすばやく削除する他の方法を教えてくれる人はいますか?

答え1

find … -exec rm {} \;rm各ファイルに対してコマンドを実行します。新しいプロセスを開始するのは非常に高速ですが、単にファイルを削除するよりもはるかに遅いです。

find … -exec rm {} +一括呼び出しされるので、はるかに高速です。バッチごとに一度実行するのにかかる費用をrm支払い、バッチ削除を複数回実行します。rm

より速いのはrmまったく電話しないことです。 Linuxのコマンドには、find一致するファイルを削除する操作があります。-delete

find ./cache -type f -mtime +0.5 -delete

ただし、追いつかない速度でファイルを生成すると、find … -exec rm {} \;設定に問題がある可能性があります。数百万のファイルが含まれている場合は、cacheより高速なアクセスのためにサブディレクトリに分割する必要があります。

答え2

以下を試してくださいxargs

find ./cache -mtime +0.5 -print0 | xargs -0 rm -f

@pradeepchhetriの説明が更新されました。

findwithを使用すると、-exec見つかったファイルごとに1回find呼び出されますrm。したがって、10,000個のファイルをたくさん見つけたら、rm10,000回呼び出したのです。

xargs出力をfindコマンド引数として扱うため、xargsは一度に処理できる数の引数をrm提供します。つまり、これによりフォーク呼び出しが減り、プログラムがより速く実行されます。rmrm -f file1 file2 ...

答え3

findが最善(最も簡単で慣用的な)方法ですが、

find $dir -exec rm {} +

そのディレクトリを横に移動し(プログラム用)、新しいディレクトリを作成して削除できます。

mv $idr old$dir && mkdir $dir && rm -rf old$dir

しかし、問題は生成されるファイルが多すぎる可能性があります。新しいファイルを作成するのではなく、既存のファイルに追加するようにプログラムを変更してみてはいかがでしょうか。その後、この(ログファイル)を横に移動すると、プログラムは新しいファイルを作成/追加できます。

fd = open("logfile","a+");

答え4

できるだけ早く多くのファイルを削除したい場合は問題ありませんが、システムls -f1 /path/to/folder/with/many/files/ | xargs rmにIOの問題がある可能性があり、削除操作中にアプリケーションがクラッシュする可能性があるため、本番システムではこれを実行しないことをお勧めします。

このスクリプトは多くのファイルで動作し、システムのioloadには影響しません。

#!/bin/bash

# Path to folder with many files
FOLDER="/path/to/folder/with/many/files"

# Temporary file to store file names
FILE_FILENAMES="/tmp/filenames"

if [ -z "$FOLDER" ]; then
    echo "Prevented you from deleting everything! Correct your FOLDER variable!"
    exit 1
fi

while true; do
    FILES=$(ls -f1 $FOLDER | wc -l)
    if [ "$FILES" -gt 10000 ]; then
        printf "[%s] %s files found. going on with removing\n" "$(date)" "$FILES"
        # Create new list of files
        ls -f1 $FOLDER | head -n 5002 | tail -n 5000 > "$FILE_FILENAMES"

        if [ -s $FILE_FILENAMES ]; then
            while read FILE; do
                rm "$FOLDER/$FILE"
                sleep 0.005
            done < "$FILE_FILENAMES"
        fi
    else
        printf "[%s] script has finished, almost all files have been deleted" "$(date)"
        break
    fi
    sleep 5
done

関連情報