사전: 이는 일반적인 문제(모든 폴더에 해당된다고 가정)에서 특정 극단적인 경우로 발전했습니다.
저처럼 궁금해하시는 분들도 계실 것 같아 질문을 삭제하지 않고 다시 작성하기로 했습니다.
내 홈 폴더에 직접 포함된 모든 항목(도트 파일 및 폴더 제외)을 나열하고 싶다고 가정해 보겠습니다. 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
-perm
at을 사용 find
해서 2> /dev/null
해결할 수 있다는 건 알지만 , 제가 정말 놀랐던 점은,/home/user/.gvfs
이미 목록에 포함되어 있습니다.(다른 모든 포인트 항목은 제외되지만)! ! !
나는 관찰력이 부족한 일부 사람들이 오류를 떨쳐버리고 2> /dev/null
계속 나아가려고 노력할 것이라고 확신합니다. ...만약에1> /dev/null
100줄로 구성된 긴 목록에서는 명령을 사용하기 전에 add와 같은 메서드를 사용하여 명시적으로 오류를 확인 해야 하기 때문에 완전히 오류를 인식합니다 .
디렉토리/트리가 실제로 무시됩니까?
이것이 방지되거나 최소한 방지되어야 함에도 불구하고 액세스를 시도하는 이유는 무엇입니까 find
? 예를 들어 매뉴얼 페이지에서:/home/user/.gvfs
-maxdepth 1
-prune
'-prune' 작업(만추가 하락 방지[...])
내 시스템에 설치된 이전 매뉴얼 페이지에도 -path
다음과 같이 나와 있습니다.
도착하다전체 디렉터리 트리 무시, 트리의 모든 파일을 확인하는 대신 -prune을 사용하세요.
"무시된" 디렉토리 자체의 위험 목록입니다!
모든 것이 실제로 무시되는 경우 /home/user/.*
내 질문의 두 번째 부분은 필요하지 않을 수 있습니다. 이는 내부 오류로 인한 것 같습니다.
왜 /home/user/.gvfs
여전히 목록에 있으며 어떻게 방지할 수 있습니까? -user
/ -perm
및 2> /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 ')'
. (이것은 -true
GNU 확장입니다. 이식 가능한 확장도 가능 ! -name ''
하지만 이식 가능한 확장은 정확함을 보장합니다. '(' -prune -o ! -prune ')'
)
이제 코드 자체에 몇 가지 문제가 있습니다. 존재하다:
find $HOME/ -mindepth 1 -maxdepth 1 -path "$HOME/.*" -prune -o -print
- 대부분의 Bourne 유사 쉘에서는
$HOME/
이를 인용해야 합니다. 그렇지 않으면$HOME
확장이 분할+글로브의 영향을 받습니다. 이렇게 쓸 수도 있습니다~/
. -prune
find
디렉토리에 들어가지 말라고 하더군요 . 최상위(깊이 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)