"-prune"에도 불구하고 "find"가 여전히 .gvfs에 액세스하려고 시도하고 심지어 이를 출력에 포함시키려고 하는 이유는 무엇입니까?

"-prune"에도 불구하고 "find"가 여전히 .gvfs에 액세스하려고 시도하고 심지어 이를 출력에 포함시키려고 하는 이유는 무엇입니까?

사전: 이는 일반적인 문제(모든 폴더에 해당된다고 가정)에서 특정 극단적인 경우로 발전했습니다.
저처럼 궁금해하시는 분들도 계실 것 같아 질문을 삭제하지 않고 다시 작성하기로 했습니다.


내 홈 폴더에 직접 포함된 모든 항목(도트 파일 및 폴더 제외)을 나열하고 싶다고 가정해 보겠습니다. IMHO 다음 find 명령이 이 작업을 수행해야 합니다..hidden( 파일을 사용하면 "숨겨진 프로젝트"가 다를 수 있기 때문에 "도트 프로젝트"라고 명시적으로 썼습니다 ):

find $HOME/ -mindepth 1 -maxdepth 1 -path "$HOME/.*" -prune -o -print

-mindepth 1$HOME 자체를 포함하지 말고 -maxdepth 1하나의 폴더 수준으로 제한하고 -path "$HOME/.*" -prune홈 폴더에서 점으로 시작하는 항목을 제외하고 -o -print기본매뉴얼 페이지.

여태까지는 그런대로 잘됐다. 그것은 일종의 작동합니다(권한이 없는 도트 폴더가 있더라도).하지만$HOME/.gvfs전혀 액세스할 수 없어야 하지만 다음과 같은 이유로 질식하기 시작합니다 -path ... -prune.

/home/user/file a
/home/user/folder b
...
find: '/home/user/.gvfs': Permission denied
/home/user/.gvfs
...
/home/user/file z

-permat을 사용 find해서 2> /dev/null해결할 수 있다는 건 알지만 , 제가 정말 놀랐던 점은,/home/user/.gvfs이미 목록에 포함되어 있습니다.(다른 모든 포인트 항목은 제외되지만)! ! !
나는 관찰력이 부족한 일부 사람들이 오류를 떨쳐버리고 2> /dev/null계속 나아가려고 노력할 것이라고 확신합니다. ...만약에1> /dev/null100줄로 구성된 긴 목록에서는 명령을 사용하기 전에 add와 같은 메서드를 사용하여 명시적으로 오류를 확인 해야 하기 때문에 완전히 오류를 인식합니다 .


디렉토리/트리가 실제로 무시됩니까?

이것이 방지되거나 최소한 방지되어야 함에도 불구하고 액세스를 시도하는 이유는 무엇입니까 find? 예를 들어 매뉴얼 페이지에서:/home/user/.gvfs-maxdepth 1-prune

'-prune' 작업(만추가 하락 방지[...])

내 시스템에 설치된 이전 매뉴얼 페이지에도 -path다음과 같이 나와 있습니다.

도착하다전체 디렉터리 트리 무시, 트리의 모든 파일을 확인하는 대신 -prune을 사용하세요.

"무시된" 디렉토리 자체의 위험 목록입니다!

모든 것이 실제로 무시되는 경우 /home/user/.*내 질문의 두 번째 부분은 필요하지 않을 수 있습니다. 이는 내부 오류로 인한 것 같습니다.
/home/user/.gvfs여전히 목록에 있으며 어떻게 방지할 수 있습니까? -user/ -perm2> /dev/null모든 find명령(적어도 작업 -prune) 을 조작할 필요가 없는 방법이 있습니까 ?

향후 활용 -> 효율성?

실제로 무시되고 있는 -prune(또는 적어도 무시되는 -path ... -prune) 것은 무엇입니까?

(거의) 모든 파일이 여전히 검사 중이 라면 이 복잡한 옵션 사용을 포기하고 대신 or 를 -prune사용하겠습니다 . 특히 오류가 발생하기 쉬우므로 더욱 그렇습니다. !-not-prune

답변1

그것은 것 같다실수GNU 구현에서 find트리거는 (파일의 메타데이터를 검색하는) 시스템 호출 lstat()인 것으로 보입니다 .fstatat()EACCESS허가가 거부되었습니다) 파일에 .gvfs.

이는 파일이 FUSE 기반 파일 시스템의 마운트 지점이기 때문에 일반적으로 Linux에서 발생하지만 -o allow-other이 옵션은 사용되지 않았습니다. 이는 접근할 수 없는 영역을 가리키는 심볼릭 링크가 있는 find -L/에서도 발생할 수 있습니다 .find -follow

여기서 내가 찾은 것은 -prune이러한 파일에 대해 반환된다는 것 입니다.잘못된-prune문서화된(및 POSIX 필수) 항상 반환되는 것처럼 이는 분명히 버그입니다.진짜.

버그가 수정될 때까지 해결 방법으로 다음 -prune으로 대체할 수 있습니다 '(' -prune -o -true ')'. (이것은 -trueGNU 확장입니다. 이식 가능한 확장도 가능 ! -name ''하지만 이식 가능한 확장은 정확함을 보장합니다. '(' -prune -o ! -prune ')')

이제 코드 자체에 몇 가지 문제가 있습니다. 존재하다:

find $HOME/ -mindepth 1 -maxdepth 1 -path "$HOME/.*" -prune -o -print
  • 대부분의 Bourne 유사 쉘에서는 $HOME/이를 인용해야 합니다. 그렇지 않으면 $HOME확장이 분할+글로브의 영향을 받습니다. 이렇게 쓸 수도 있습니다 ~/.
  • -prunefind디렉토리에 들어가지 말라고 하더군요 . 최상위(깊이 0) 디렉토리를 제외한 모든 디렉토리로 내려가는 maxdepth 1것을 중지하므로 여기서는 중복됩니다 .find$HOME/
  • -path패턴을 채택하세요. 이는 콘텐츠가 $HOME패턴으로 처리된다는 의미입니다. $HOME예를 들어, 귀하가 이면 /home/[112] me에서는 일치 하지만 에서는 -path '/home/[112] me/.*'일치하지 않습니다 . 또한 여기서는 전체 경로를 일치시킬 필요가 없으며, 대신 파일 이름을 일치시킬 수 있습니다 ./home/2 me/.foo/home/[112] me/.foo-name '.*'
  • *GNU에만 find일치수치, 따라서 다음 .*으로 시작하는 파일 이름과 일치합니다.. 그리고또한 유효한 문자를 형성하는 일련의 바이트로 구성됩니다. 따라서 C각 바이트 시퀀스가 ​​유효한 문자(예: 로케일)를 형성하는 로케일의 숨겨진 파일을 일치시키는 데에만 이를 사용할 수 있습니다 .

따라서 여기서 요점이 전체 경로와 함께 HOME 디렉터리에 숨겨져 있지 않은 파일을 나열하는 것이라면 다음을 수행할 수 있습니다.

LC_ALL=C find ~/ -mindepth 1 -maxdepth 1 ! -name '.*'

이는 또한 GNU find오류를 방지합니다.

또는 표준 동등 항목( /./경로에 a를 추가하더라도):

LC_ALL=C find ~/. ! -name . -prune ! -name '.*'

find(여기서 파일에서 GNU 오류가 발생합니다.아니요시작하는 것은 .불가능 lstat()하지만 위의 오류 설명에서 볼 수 있듯이 lstat()불가능한 파일이 보고되는지 여부는 구현마다 크게 다릅니다.

여기서는 다음을 사용합니다 zsh.

print -rC1 ~/*(ND)

또는 다음과 같이 정렬되는 것을 원하지 않는 경우 find:

print -rC1 ~/*(NDoN)

관련 정보