여러 하위 디렉터리에 많은 수의 파일이 포함된 디렉터리에서 오래된 파일을 삭제하고 싶습니다.
저는 다음 접근 방식을 사용하려고 합니다. 인터넷 검색 후에 이것이 권장되고 효과적인 접근 방식인 것 같습니다.
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
파일이 필요하지 않으며 파일 하나만 찾아서 삭제하고 제안한대로 다음 단계로 넘어갑니다.
이번에는 간단한 인쇄 변형을 사용하여 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 3
한 줄에 세 개의 파일만 첫 번째 인수로 추가하여 읽을 수 있는 출력을 얻는 데 도움이 될 수 있습니다.xargs
모든 것이 잘 작동한다면 echo
이전 것을 삭제 rm
하고 다시 실행하십시오.
그래야지훨씬 더 빨리;
수백만 개의 파일에 대해 이야기하고 있다면(당신이 작성한 총 파일 수는 6억 개입니다) 고려해야 할 사항이 더 있습니다:
대부분의 프로그램(포함 find
)은 라이브러리 호출을 사용하여 디렉토리를 읽습니다.readdir (3)
. 32KB 버퍼는 일반적으로 디렉토리를 읽는 데 사용됩니다. 이는 디렉토리가 크고 잠재적으로 긴 파일 이름의 거대한 목록을 포함하는 경우 문제가 될 수 있습니다.
이 문제에 대한 해결책은 시스템 호출을 직접 사용하여 디렉토리 항목을 읽는 것입니다.
getdents (2)
, 보다 적절한 방식으로 버퍼링을 처리합니다.
자세히보다8백만 개의 파일이 포함된 디렉토리를 나열할 수 있습니다! 하지만 ls를 사용하지 않는 ..
(디렉터리당 일반적인 파일 수, 디렉터리당 디렉터리 수, 최대 경로 깊이, 사용되는 파일 시스템에 대한 세부 정보를 질문에 추가할 수 있다면 흥미로울 것입니다.)
(그래도 속도가 느린 경우 파일 시스템 성능 문제를 확인해야 합니다.)
답변2
나는 항상 이 옵션을 사용하고 싶습니다 -exec
.
find . -mindepth 2 -mtime +5 -type f -exec rm -f {} \;
삭제될 파일은 나중에 인쇄 -v
되지만 rm
콘솔에 출력을 표시하면 속도가 약간 느려지는 것처럼 보이므로 속도가 요구 사항이라면 무시하겠습니다.
답변3
이 옵션과 함께 rsync를 사용하는 것이 훨씬 빠릅니다 --delete
. 대상 폴더에 동기화할 빈 폴더만 있으면 모든 것이 정말 빠르게 진행됩니다. 이 rm -rf
명령은 삭제하기 전에 각 inode의 링크를 확인하기 때문에 속도가 느립니다.