찾는 방법 -f -print -o -name을 입력하세요. -o -prune이 정말 작동하나요?

찾는 방법 -f -print -o -name을 입력하세요. -o -prune이 정말 작동하나요?

git배경으로 저는 hp-ux 11.11(11v1) 시스템을 사용하고 있습니다. 많은 파일을 제외하기 위해 광범위한 .gitignore 파일을 만들고 있습니다. 내 .gitignore는 기본적으로 "이 디렉토리를 제외한 모든 것을 무시하지만 이 디렉토리 아래의 이러한 패턴도 무시합니다."라고 말합니다. 정확한 방법과 이유는 질문과 완전히 관련이 없습니다.

git add내 목표는 실행하기 전에 예상한 결과를 얻는지 확인하는 것입니다 git add. 이를 달성하기 위해 주어진 디렉토리의 파일에 대해 테스트를 실행하고 있습니다 git check-ignore.

내 접근 방식은 일반적으로 다음과 같습니다.

find test2 -type f -exec git check-ignore -v -n {} \; grep !

명확하게 하기 위해 저장소는 루트 디렉터리(/.git)(실제로는 /baz/dev/myRepo/.git에 심볼릭 링크됨)에 있으므로 git status/에서 호출합니다. 또한 경로가 내가 볼 것으로 예상하는 것과 일치하고 작업이 git반환된 경로의 형식과 일치하도록 find from /를 호출합니다.find-exec

표준 출력은 다음과 같습니다.

.gitignore:208:!test2/backupScripts/**  test2/backupScripts/CV_PostJob.sh
.gitignore:208:!test2/backupScripts/**  test2/backupScripts/CV_PostJob.sh.old
.gitignore:208:!test2/backupScripts/**  test2/backupScripts/CV_PreJob.sh
.gitignore:208:!test2/backupScripts/**  test2/backupScripts/CV_PreJob.sh.old
.gitignore:208:!test2/backupScripts/**  test2/backupScripts/CV_ScanCheck.sh
.gitignore:208:!test2/backupScripts/**  test2/backupScripts/oldCH.txt
.gitignore:212:!test2/scripts/**        test2/scripts/deprecated/CommvaultBackupScript.sh
.gitignore:212:!test2/scripts/**        test2/scripts/deprecated/NetBackupScript.sh
.gitignore:212:!test2/scripts/**        test2/scripts/benchmark.sh
.gitignore:212:!test2/scripts/**        test2/scripts/migrateVolumeSync.sh
.gitignore:212:!test2/scripts/**        test2/scripts/test.sh
.gitignore:206:!test2/* test2/CommvaultBackupScript.sh
.gitignore:206:!test2/* test2/NetBackupScript.sh
.gitignore:206:!test2/* test2/benchmark.sh
.gitignore:206:!test2/* test2/test.sh

일반적으로 이 기술은 잘 작동하지만 경우에 따라 .gitignore의 패턴에 의해 제외되는 많은 수의 파일을 포함하는 /test2/foo디렉터리 가 있습니다./test2/bar

#Ignore everything
*

#add back /test2
!test2
!test2/**
#reignore foo and bar
test2/foo
test2/bar

find test2 -exec git check-ignore따라서 핵심 질문은 다음과 같습니다. 열거하지 않고 명령을 작성할 필요 없이 test2/foo 및 test2/bar를 실행할 수 있기를 원합니다 . find test2 -name foo -prune -o -name bar -prune -o -type f -exec git check-ignore {} \;특히 무시된 하위 디렉터리가 12개일 수 있는 경우에 실제로는 test2/의 파일이 올바르게 포함되는지 확인한 다음 다시 실행하여 test2/backupScripts와 같은 작은 하위 디렉터리 하나를 확인합니다.

find . -type f -print -o -name . -o -prune궁극적으로 POSIX 호환 명령 을 -exec와 함께 실행하여 find가 상대 경로가 아닌 절대 경로인 git check-ignore에 경로를 전달할 수 있도록 조정하고 싶습니다 . 그러나 이 명령이 정확히 어떻게 작동하는지 모르겠습니다. 실제로 실행되는 루트 디렉터리만 검색한다는 것을 확인할 수 있습니다.

내 작업은 최신 버전의 findutils가 없고 플랫폼에 사용할 수 있는 GNU findutils가 없다는 사실로 인해 제한됩니다. 따라서 -maxlength 옵션을 사용할 수 없습니다.

export GIT_DISCOVERY_ACROSS_FILESYSTEM=1또한 /test2는 마운트 지점이므로 /.git에 있는 저장소에 대해 test2에서 git을 실행하려면 마운트 지점 경계를 탐색할 수 있도록 Git 환경( )을 수정해야 합니다 ( cd test2 && find . -type f -exec git check-ignore --no-index -v -n {} \; -o -name . -o -prune | grep !현재로서는 잘 작동함). 가능하다면 (시스템에서 Git을 다른 용도로 사용하기 위해) 이 작업을 수행하고 싶지 않습니다.

그렇다면 정확히 어떻게 작동합니까 find . -type f -print -o -name . -o -prune? 하나 이상의 점을 /에서 호출할 수 있는 일부 경로 지정으로 대체하여 수정할 수 있습니까? 아니면 옵션이 이 특정 순서로 제공될 때 특정 기능을 수행하는 일종의 "마법"(예: 옵션이 이 순서로 제공되는 경우에만 원하는 동작이 도출될 수 있음)입니까? 이 특정 명령을 Google에서 검색하면 이 특정 답변 자체를 여러 언어로 다시 게시하는 것 외에는 아무것도 반환되지 않는 것 같습니다.재귀 검색 없음

나는 다음을 수행하여 이 특정 명령의 동작을 분석하려고 했습니다.

cd /
find test2 -type f -print -o -name . -o prune
#no output

cd /test2
find . -type f -print -o -name . -o -prune
#get files in CWD as expected

find . -type f -print 
#gives me all files and directories below this, as you would expect

find . -type f -print -o -name . 
#gives the same as the prior command

find . -name . 
#gives just the CWD entry (.)

find . -name . -o -prune 
#gives just the files and folders in CWD, including the (.) entry

cd /
find test2 -name test2 -o -prune 
#also gives the files and folders directly in test2, including test2 itself

find test2 -name test2 -o -prune -o -type f -print 
#no output

find test2 -name test2 -prune 
#returns just test2 itself

find test2 -type f -print -o -name test2 -prune 
#predictably gives no output, as test2 is pruned

find test2 -type f -print -o -name foo -prune 
#gives full directory list except for /test2/foo, as expected.

find test2 -type f -print -o -name "test2/*" -prune 
#gives full directory list, as a / will never be in the "base" name which find tests.

cd /
find test2/* -type f -print -o -prune 
#this is the closest, same as "find . -name . -o -prune" but with cd to test2 first.

답변1

find . -type f -print -o -name . -o -prune

보다 정식적인 접근 방식과 비교하여 하위 디렉터리 대신 현재 디렉터리에서 일반 파일을 찾는 더 정교한 방법은 다음과 같습니다.

find . ! -name . -prune -type f

GNU 구현을 사용하여 작성할 수도 있습니다 find(또는 GNU find-mindepth/implementation 복사 -maxdepth).

find . -mindepth 1 -maxdepth 1 -type f

( -mindepth이 경우 중복되므로 (깊이 0)은 -type f제외됩니다 ..)

존재하다:

find . -type f -print -o -name . -o -prune

.find파일 검색이 시작되는 파일입니다.

.은(는) 일반 파일 자체가 아니므로 인쇄되지 않으며 -o첫 번째 파일의 오른쪽 부분이 테스트됩니다. -name .일치하므로 식이 true로 확인되고 -prune실행되지 않습니다. 왜냐하면 전체 find표현식에는 a -print가 포함되어 있기 때문입니다.행동조건자, 해당 파일의 전체 표현식이 true로 확인되더라도 암시적으로 아무것도 인쇄되지 않습니다.

이제 .정리 작업이 없고 디렉토리이므로 find해당 내용을 읽고 그 안에 있는 모든 파일(특수 항목 제외)에 표현식이 적용 .됩니다 ...

이를 위해 다음 유형의 파일에 대해정기적인, -print실행됩니다. 다른 유형의 파일의 경우 -name .일치하는 항목이 없으므로 -prune실행됩니다. 해당 디렉토리 유형 파일의 경우 이는 find해당 파일로 내려갈 수 없음을 의미합니다.

따라서 중요한 사항은 다음과 같습니다.

  • 정기적인( f유형) 인쇄할 파일
  • .(최상위 디렉터리) 이외의 디렉터리는 정리되므로 find가 하위 디렉터리로 드롭다운되지 않습니다.

답변2

에서 man find:

-prune
True; if the file is a directory, do not descend into it.

일반적으로 -path옵션과 함께 사용됩니다.

find $HOME -path $HOME/.config -prune \
  -type f -mtime 0

오늘 수정된 파일은 검색 $HOME되고 무시 됩니다 .$HOME/.config

관련 정보