대량의 파일을 삭제하는 더 빠른 방법

대량의 파일을 삭제하는 더 빠른 방법

많은 수의 캐시 파일이 빠르게 생성되는 디렉터리가 있습니다. 이 파일은 너무 작기 때문에 모든 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발견된 각 파일에 대해 한 번씩 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

관련 정보