찾기: 삭제가 허용된 파일만 삭제

찾기: 삭제가 허용된 파일만 삭제

find특정 기준과 일치하는 파일을 삭제하는 데 사용하는 방법 :

find -type f [more criteria] -delete

일반적으로 이것은 잘 작동하지만 다른 사용자가 만든 하위 디렉터리에 문제가 있습니다. 제가 아는 한, 그 사용자가 파일 삭제를 허용합니까?상위 디렉토리에 대한 내 권한에 따라 다릅니다.. 따라서 다른 사용자가 만든 하위 디렉터리에 포함된 파일에 대해서는 위 명령이 실패합니다.

fbrucker@host /tmp $ ls -lh
total 4,0K
drwxrwxr-x 2 root root 4,0K Jun 15 11:44 foo/

fbrucker@host /tmp $ ls -lh foo/
total 0
-rw-rw-r-- 1 fbrucker fbrucker 0 Jun 15 11:44 a
-rw-rw-r-- 1 root     root     0 Jun 15 11:44 b

fbrucker@host /tmp $ find -type f -delete
find: cannot delete ‘./foo/b’: Permission denied
find: cannot delete ‘./foo/a’: Permission denied

괜찮습니다. 파일을 삭제할 수는 없지만 권한이 부족하면 find0이 아닌 상태로 종료됩니다. 나는 이런 상황을 피하고 싶다.

삭제할 수 없는 파일을 삭제하기 전에 어떻게 필터링할 수 있나요?

오류 메시지를 필터링하면 됩니다.아니요여전히 0이 아닌 종료 코드가 남으므로 이것으로 충분합니다. 또한 종료 코드를 완전히 무시하는 것은 다른 오류를 포착하고 싶기 때문에 작동하지 않습니다(실제 find명령은 더 복잡합니다. 예를 find /somedir -type f -delete들어아니요/somedir존재하지 않을 때 발생하는 오류는 무시합니다.)

find파일(예:,,)에 대한 권한을 테스트한다는 것을 알고 있지만 -perm여기에는 적용되지 않는 것 같습니다. 예를 들어,-readable-writable

fbrucker@host /tmp $ find -type f -writable
./foo/a

foo/a필요한 권한이 없어서 삭제할 수 없는데도 foo.

-deletable테스트 같은 것을 찾고 있는데 존재하지 않는 것 같습니다.

답변1

예, 상위 디렉터리에 대한 쓰기 권한이 필요하며 해당 디렉터리에 비트가 설정된 경우 링크를 t해제하려는 디렉터리 또는 파일의 소유자여야 합니다. 이 모든 것은 ACL과 같은 다른 보안 제어가 없고 파일이 위치한 FS는 읽기 전용이 아니므로제거 가능검사는 더 복잡합니다.

for -readable// -writable( -executable비표준) find해당 access(R_OK/W_OK/X_OK)시스템 호출을 사용할 수 있지만 이에 상응하는 것은 없습니다.풀리다하나의 문서.

GNU find4.9.0 이상을 사용하면 다음과 같이 근사할 수 있습니다.

find . -depth -type d -writable '(' -uid "$EUID" -o ! -perm -o=t ')' -print0 |
  find -files0-from - -mindepth 1 -maxdepth 1 -type f -delete

zsh( 또는 과 같은 bash쉘 설정을 가정합니다 $EUID. 그렇지 않은 경우 해당 을 사용하십시오 "$(id -u)").

이렇게 하면 소유한 파일이 소유하지 않은 -bit 디렉터리에 남게 되며 t해당 파일을 별도로 처리해야 합니다.

find . -depth -type d -writable ! -uid "$EUID" -perm -o=t -print0 |
  find -files0-from - -mindepth 1 -maxdepth 1 -type f -uid "$EUID" -delete

pipefail첫 번째 find.

이전 버전의 GNU에서는 find언제든지 다음을 수행할 수 있습니다.

find . -depth -type d -writable '(' -uid "$EUID" -o ! -perm -o=t ')' -exec sh -c '
  exec find "$@" -mindepth 1 -maxdepth 1 -type f -delete
  ' sh {} +

액세스 권한으로 인한 파일 링크 해제 실패를 무시하는 것이 요점이라면 다음과 같이 할 수 있습니다.

set -o pipefail
find . -depth -type f -print0 |
  perl -l -0ne '
    unless (unlink($_) || $!{EACCES}) {
      warn "$_: $!\n";
      $ret = 1;
    }
    END {exit $ret}'

답변2

한 가지 해결 방법 은 호출의 종료 코드가 무시되므로 대신 -exec rm {} \;사용 하는 것입니다 .-deletefind-exec

관련 정보