find 명령에서 하나의 특정 경로를 제외한 모든 하위 디렉터리 제외

find 명령에서 하나의 특정 경로를 제외한 모든 하위 디렉터리 제외

find특정 디렉터리 경로를 무시하고 현재 하위 디렉터리에서 특정 확장자를 가진 모든 파일을 검색하는 명령을 사용합니다 .

find -L . \( -wholename "*/ignoredPath" -o -wholename "*/ignoredPath2" \) -prune -o -name "*.ext"

이것은 잘 작동하지만 이제 정확한 하위 디렉터리 중 하나를 제외한 다른 경로를 무시하고 싶습니다. 무시할 모든 하위 디렉터리를 나열하지 않고 이 작업을 수행하려면 어떻게 해야 합니까?

예를 들어 다음과 같은 폴더 트리가 있는 경우:

*/base/pathToIgnore1
*/base/subdir/requiredPath
*/base/subdir/pathToIgnore2
*/base/subdir/pathToIgnore3
*/base/pathToIgnore4

경로를 제외한 모든 하위 디렉터리를 find무시하는 명령을 어떻게 작성할 수 있습니까 ?base*/base/subdir/requiredPath

나는 다음과 같은 것을 시도했습니다

find -L . \( -wholename "*/ignoredPath" -o -wholename "*/ignoredPath2" -o \( -wholename "*/base" -a ! -wholename "*/base/subdir/requiredPath" \) \) -prune -o -name "*.ext"

하지만 작동하지 않으며 모든 base하위 디렉터리가 무시됩니다.

답변1

find -L . \
  \( -type d \
    \( -path "*/ignore" -o -path "*/indeed" -o \
      \( -path "*/subdir/*" ! -path "*/subdir/save" \
      \) \
    \) \
  \) \
  -prune -o -print

추가 필터(예 -name "*.ext": )를 원할 경우 필터를 앞에 배치해야 합니다 -print. 마지막 부분은 이렇습니다

  -prune -o \( -name "*.ext" \) -print

쓰기 쉽고 읽기 쉽도록 이름을 변경했습니다. 로 시작하는 이름은 i무시됩니다. s로 시작하는 이름이 표시됩니다. 로 끝나는 이름은 file파일입니다.

내 나무는 다음과 같습니다

$ find -printf "%y %p\n"
d .
d ./base
d ./base/subdir
d ./base/subdir/inform
f ./base/subdir/inform/imagefile
d ./base/subdir/isolate
f ./base/subdir/isolate/individualfile
f ./base/subdir/whatwhatinthefile
d ./base/subdir/save
f ./base/subdir/save/soundfile
f ./base/superfile
d ./base/indeed
f ./base/indeed/itemfile
d ./base/show
f ./base/show/startfile
d ./base/ignore
f ./base/ignore/importantfile

위 명령의 출력:

.
./base
./base/subdir
./base/subdir/whatwhatinthefile
./base/subdir/save
./base/subdir/save/soundfile
./base/superfile
./base/show
./base/show/startfile

whatwhatinthefile에서 base/subdir이러한 파일을 원하지 않으면 명시적 으로 base/subdir제외해야 합니다. 시도해봤는데 명령줄이 너무 보기 흉해졌습니다.

사용 사례에 따라 다음과 같이 셸 함수를 정의하는 것이 더 쉬울 수 있습니다.

contrivedfind() {
  find -L . \
    \( -type d \
      \( -path "*/ignore" -o -path "*/indeed" -o -path "*/subdir" \
      \) \
    \) \
    -prune -o -print
  find -L ./base/subdir/save
}

이제 출력은 다음과 같습니다.

.
./base
./base/superfile
./base/show
./base/show/startfile
./base/subdir/save
./base/subdir/save/soundfile

이전과 유일한 차이점은 ./base/subdir항목이 없다는 것입니다. 그러나 어쨌든 파일을 필터링하고 싶기 때문에 그것이 중요하지 않다고 생각합니다.

이전과 마찬가지로 -print첫 번째 필터 앞에 추가 필터를 배치 해야 하며 find, 이번에는 두 번째 필터의 끝에도 배치해야 합니다 find.

답변2

*/base자체적으로 일치하는 것을 방지해야 합니다 .

편집 1:

find -L . -type d \
  \( -wholename "*/ignoredPath" -o -wholename "*/ignoredPath2" -o \
  \( -wholename "*/base/*" -a \
  \( ! -wholename "*/base/subdir" -a ! -wholename "*/base/subdir/*" \) \) -o \
  \( -wholename "*/base/subdir/*" -a \
  \( ! -wholename "*/base/subdir/requiredPath" -a ! -wholename "*/base/subdir/requiredPath/*" \) \) \) \
  -prune -o -print

이는 약간 까다롭습니다. subdir2존재하지 않을 수 있는 디렉터리가 실수로 일치하는 것을 방지합니다. 하지만 당신은 결코 알지 못합니다...:-)

관련 정보