특정 하위 디렉터리를 제외한 모든 파일을 삭제하려면 찾기를 사용하세요.

특정 하위 디렉터리를 제외한 모든 파일을 삭제하려면 찾기를 사용하세요.

a하위 폴더의 모든 파일을 제외하고 특정 기간 동안 폴더에 액세스하지 않은 모든 파일을 반복적으로 삭제하고 싶습니다 b.

find a \( -name b -prune \) -o -type f -delete

그러나 오류 메시지가 나타납니다.

find: -delete 작업은 자동으로 -deep을 활성화하지만 -prune은 -deep이 적용되는 동안 아무 작업도 수행하지 않습니다. 계속하려면 -length 옵션을 명시적으로 사용하세요.

-depth추가하면 모든 파일이 포함 됩니다 .b아니요발생하다.

이를 수행하는 안전한 방법을 아는 사람이 있습니까?

답변1

한 가지 방법은 -exec rm대신 사용하는 것입니다 -delete.

find a \( -name b -prune \) -o -type f -exec rm {} +

또는 -not -path대신 사용하십시오 -prune:

find a -not -path "*/b*" -type f -delete

-prune다음과 충돌하는지 설명하세요 -delete.

힌트를 주고 만들기 가 효과가 없기 때문에 with를 사용하려고 하면 -delete불만 사항을 알게 될 것입니다 .-prune-delete-depth-depth-prune

다음을 사용하거나 사용하지 않고 find 동작을 관찰합니다 -depth.

$ find foo/
foo/
foo/f1
foo/bar
foo/bar/b2
foo/bar/b1
foo/f2

단일 디렉터리 내의 순서는 보장되지 않습니다. 그러나 디렉토리는 내용보다 먼저 처리됩니다. foo/before foo/*foo/barbefore 를 참고하세요 foo/bar/*.

이것은 되돌릴 수 있습니다 -depth.

$ find foo/ -depth
foo/f2
foo/bar/b2
foo/bar/b1
foo/bar
foo/f1
foo/

현재가 foo/*before보다 앞에 온다는 점에 유의하세요 foo/. 와 동일합니다 foo/bar.

추가 설명:

  • -prunefind가 디렉토리로 내려오는 것을 방지합니다. 즉, -prune디렉터리의 내용을 건너뜁니다. 귀하의 경우 -name b -prune이는 find가 해당 이름의 디렉토리에 도달하면 b모든 하위 디렉토리를 포함하여 해당 디렉토리를 건너뛰는 것을 의미합니다.
  • -depthfind가 디렉토리 자체보다 먼저 디렉토리의 내용을 처리하도록 합니다. 이는 find가 디렉토리 항목 처리를 시작할 때 b그 내용이 이미 처리되었음을 의미합니다. 따라서 -prune유효하지 않음과 -depth유효함.
  • -delete즉, -depth콘텐츠를 먼저 삭제한 다음 빈 디렉터리를 삭제할 수 있습니다. -delete비어 있지 않은 디렉토리 삭제를 거부합니다.

대체 방법 설명:

find a -not -path "*/b*" -type f -delete

기억하기가 더 쉬울 수도 있고 그렇지 않을 수도 있습니다.

명령은 여전히 ​​디렉토리에 들어가 b그 안에 있는 모든 파일을 처리하지만 거부합니다 -not. 디렉터리가 큰 경우 b성능 문제가 발생할 수 있습니다 .

-path다르게 작동합니다 -name. 전체 경로 -name가 아닌 (파일 또는 디렉터리의) 이름만 일치합니다 . -path예를 들어 경로를 관찰해 보세요 /home/lesmana/foo/bar. -name bar이름이 이기 때문에 일치합니다 bar. -path "*/foo*"문자열이 /foo경로에 있기 때문에 일치합니다. -path사용하기 전에 이해해야 할 몇 가지 복잡성이 있습니다. 자세한 내용은 매뉴얼 페이지를 읽어보십시오 find.

이것이 100% 완벽한 것은 아니라는 점에 유의하시기 바랍니다. "오탐지" 가능성이 있습니다. 위의 명령이 작성된 방식은 b이름이 (양수)로 시작하는 상위 디렉토리가 있는 모든 파일을 건너뜁니다. 그러나 트리의 위치에 관계없이 이름으로 시작하는 모든 파일을 건너뜁니다 b(오탐). 이는 .보다 나은 표현을 작성하면 해결될 수 있습니다 "*/b*". 이것은 독자들에게 연습문제로 남겨둔다.

나는 당신이 aand를 b자리 표시자로 사용하고 있고 실제 이름은 allosaurusand에 더 가깝다고 가정합니다 brachiosaurus. 이를 대체하면 오탐 brachiosaurus( bfalse positive) 수가 크게 줄어들 것입니다.

적어도 거짓 긍정은 다음과 같습니다.아니요너무 비참하지 않도록 삭제했습니다. 또한 먼저 명령 없이 명령을 실행하고 -delete(암시적인 명령을 입력해야 함 -depth) 출력을 검사하여 오탐지를 확인할 수 있습니다 .

find a -not -path "*/b*" -type f -depth

답변2

rm대신 사용하십시오 -delete:

find a -name b -prune -o -type f -exec rm -f {} +

답변3

위의 답변과 설명이 매우 도움이 됩니다.

나는 "-exec rm {} +" 또는 "-not -path ... -delete"와 같은 해결 방법을 사용하지만 "find ... -delete"보다 훨씬 느릴 수 있습니다. NFS 파일 시스템의 깊은 디렉토리에서 "find... -delete"가 "-exec rm {} +"보다 5배 빠르게 실행되는 것을 보았습니다.

"-not path" 솔루션의 명백한 오버헤드는 제외된 디렉터리와 그 아래에 있는 모든 파일을 보는 것입니다.

"find .. -exec rm {} +"는 rm을 호출하여 시스템 호출을 수행합니다.

fstatat(AT_FDCWD, path...); 
unlinkat(AT_FDCWD, path, 0)

"find -delete"는 시스템 호출을 실행합니다.

 fd=open(dir,...);
 fchdir(fd); 
 fstatat(AT_FDCWD, filename,...)
 unlinkat(dirfd, filename,...)

따라서 "-exec rm {}+" rm 명령은 각 파일에 대해 inode 전체 경로 조회를 두 번 수행하지만 "find -delete"는 현재 디렉터리의 파일 이름을 계산하고 연결을 해제합니다. 디렉터리에서 많은 수의 파일을 삭제할 때 이는 큰 이점입니다.

(와인 모드 켜짐(죄송합니다))

-length, -delete 및 -prune 사이의 상호 작용 설계는 "-prune 디렉터리에 있는 파일 이외의 파일 삭제"라는 일반적인 작업을 수행하는 가장 효율적인 방법을 불필요하게 제거한 것 같습니다.

"-type f -delete" 조합은 디렉토리 삭제를 시도하지 않으므로 -deep 없이 실행될 수 있어야 합니다. 또는 "find"에 "-deletefile" 작업이 있으면(디렉토리를 삭제하지 않음을 의미), -깊이를 암시할 필요가 없습니다.

rm에 파일 이름을 정렬하고, 디렉토리를 열고, 전체 경로 링크를 해제하는 대신 unlinkat(dir_fd,filename)을 수행하는 옵션이 있는 경우 rm 명령에 대한 xargs 또는 find -exec 호출 속도가 빨라질 수 있습니다. -r 옵션을 사용하여 디렉터리로 재귀할 때 unlinkat(dir_fd,filename)이 수행되었습니다.

(와인 모드 꺼짐)

관련 정보