찾기 : 정리는 지정된 경로를 무시하지 않습니다.


13

검색 .git에서 제외해야합니다 find. 그것을 달성하기 위해 -path ./.git -prune스위치를 사용하고 있습니다.

$ find . -path ./.git -prune -o \( -type f -o -type l -o -type d \) | grep '.git'
./.git

그러나 이것이 .git 디렉토리의 내용을 건너 뛰더라도 디렉토리 자체가 나열됩니다. 추가하면 작동합니다.-path ./.git -prune -o -print -a

find . -path ./.git -prune -o -print -a \( -type f -o -type l -o -type d \) | grep '.git'

이것이 왜 필요한가. 두 명령 모두 동일한 출력을 가져야한다고 생각했습니다. 두 번째 구문은 매우 추악합니다.


4
필요합니다 -print. 그렇지 않으면 암시 적으로 -print전체 조건에 적용됩니다.
Stéphane Chazelas


답변:


3

man페이지 find는 다음 을 제공합니다.

-prune True; if the file is a directory, do not  descend  into  it.  If
      -depth  is  given,  false;  no  effect.  Because -delete implies
      -depth, you cannot usefully use -prune and -delete together.

따라서 첫 번째 예에서는 -path ./.git -prune사실이 아니므로 기본 동작 ( -print)이 호출되지 않으므로 행이 인쇄됩니다.


22

정리 된 디렉토리가 find명령에 의해 인쇄되는 이유 와 -prune작동 방식에 대한 다른 복잡한 세부 사항에 대해 혼란 스러웠지만 몇 가지 예를 통해 이해할 수있었습니다.

아래 예제를 실행하려면 다음 디렉토리 및 파일을 작성하십시오.

mkdir aa
mkdir bb
touch file1
touch aa/file1
touch bb/file3

이 구조를 만들려면

$ tree

.
├── aa
   └── file1
├── bb
   └── file3
└── file1

이제 find를 사용하여 이름이 지정된 디렉토리를 찾으십시오 aa. 문제 없습니다.

$ find . -type d -name aa
./aa

aa 이외의 모든 디렉토리를 찾으면 현재 디렉토리 .와를 얻습니다 ./bb.

$ find . -type d ! -name aa
.
./bb

지금까지는 좋지만, 우리가 사용할 때 -prunefind는 제거 할 디렉토리를 반환합니다.

$ find . -type d -name aa -prune
./aa

정리 된 디렉토리를 리턴하는 이유 -pruneTimo의 답변에 표시된 매뉴얼 페이지 섹션이 아니라 EXPRESSIONS섹션 에 설명되어 있습니다.

식이 이외의 조치를 포함하지 않는 경우 -prune,  -print표현식이 true 인 모든 파일에 대해 수행된다.

이는 표현식이 aa디렉토리 이름 과 일치하므로 표현식이 true로 평가되고 find -print가 전체 명령의 끝에 암시 적으로 a 를 추가하기 때문에 표현식이 인쇄 됨을 의미합니다. -print그러나 의도적으로 -o -print끝 부분에 작업 을 추가하는 경우을 추가 하지 않습니다 .

find . -type d -name aa -prune -o -print
.
./file1
./bb
./bb/file3

여기서 find 명령은 -print더 이상 암시 적을 추가하지 않으므로 정리하는 디렉토리 ( aa)가 인쇄되지 않습니다.

마지막으로, 파일 이름 패턴이 file*다음에 나오는 파일을 검색하는 절을 추가하면 -o다음 -print과 같이 두 번째 절의 끝에 를 넣어야합니다 .

find . \( -type d -name aa -prune \) -o \( -type f -name 'file*' -print \)
./file1
./bb/file3

이것이 작동하는 이유는 동일합니다. -print두 번째 절에을 넣지 않으면 조치 이외의 -prune조치 가 없으므로 find는 -print명령의 끝에 자동으로 추가 하여 -prune절이 인쇄되도록합니다. 정리 된 디렉토리 :

find . \( \( -type d -name aa -prune \) -o \( -type f -name 'file*' \) \) -print
./aa
./file1
./bb/file3

일반적으로 -print두 번째 절에 명령 을 배치해야합니다 . 원본 포스터와 같이 중간에 배치하면 정리되는 파일이 즉시 인쇄되고 두 번째 절에서 원하는 파일을 선택할 수 없으므로 올바르게 작동하지 않습니다.

find . \( -type d -name aa -prune -o -print \) -o \( -type f -name 'file*' \)
.
./file1
./bb
./bb/file3

불행히도 원래 포스터는 잘못된 위치에 배치하여 명령 -print이 잘못되었습니다. 그의 경우에는 효과가 있었지만 일반적인 경우에는 효과가 없습니다.

-prune작동 방식을 이해하는 데 어려움을 겪는 수천 명의 사람들이 있습니다 . find사람 페이지가이 명령에 대한 네버 앤딩 전 세계적으로 혼란을 방지하기 위해 업데이트해야합니다.


내 매뉴얼 페이지 (Arch Linux, find-4.6.0)에 따르면 "전체 표현식에 -prune 또는 -print 이외의 작업이 포함되어 있지 않으면 전체 표현식이 참인 모든 파일에 대해 -print가 수행됩니다." 그러나 설명대로 작동합니다.
x-yuri

0

에서 man페이지,

전체 디렉토리 트리를 무시하려면 트리의 모든 파일을 검사하지 말고 -prune을 사용하십시오. 예를 들어,`src / emacs '디렉토리와 그 아래의 모든 파일과 디렉토리를 건너 뛰고 발견 된 다른 파일의 이름을 인쇄하려면 다음과 같이하십시오.

find . -path ./src/emacs -prune -o -print

따라서 다음을 사용할 수 있습니까?

find . -path ./.git -prune -o -print

.git디렉토리가 나열되지 않습니다 .

특정 파일 이름으로 다음과 같이 할 수 있습니다.

find . -path ./.git -prune , -name filename

통지하시기 바랍니다 ,쉼표 연산자.


-1

빠르고 더러운 대안은 다음과 같습니다.

find | fgrep -v /.git

find복잡한 구문을 기억할 수 없습니다 ...

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.