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