find에서 디렉토리를 제외하는 방법 명령


1380

find모든 JavaScript 파일에 대해 명령 을 실행하려고 하는데 특정 디렉토리를 어떻게 제외합니까?

find우리가 사용 하는 코드는 다음과 같습니다 .

for file in $(find . -name '*.js')
do 
  java -jar config/yuicompressor-2.4.2.jar --type js $file -o $file
done

10
제외해야 할 디렉토리는 무엇입니까?
Archetypal 폴

11
를 사용하는 것이 좋습니다 find ... | while read -r file .... 또한 답변을 받아들이고 찬성하는 것이 좋습니다.
추후 공지가있을 때까지 일시 중지되었습니다.

에가 빠른에 대한 읽기, 느린 동안
mpapis

18
@mpapis는 읽는 동안 공백이있는 전체 줄을 올바르게 처리합니다.
Jean-Philippe Pellet

1
이름이 공백 인 파일이있는 폴더에서이를 실행하십시오 for file in $(find .); do echo "$file"; done. 공백이있는 이름은 분할되어 원하지 않습니다.
Jean-Philippe Pellet

답변:


1140

-prune스위치를 사용하십시오 . 예를 들어, misc디렉토리 를 제외하려면 -path ./misc -prune -ofind 명령에 a 를 추가 하십시오.

find . -path ./misc -prune -o -name '*.txt' -print

다음은 여러 디렉토리가있는 예입니다.

find . -type d \( -path dir1 -o -path dir2 -o -path dir3 \) -prune -o -print

여기에서 우리는 제외 DIR1 , DIR2dir3을 에 있기 때문에, find표현이 기준에 작용하는 작업입니다 -path dir1 -o -path dir2 -o -path dir3(경우 DIR1 또는 dir2는 또는 dir3가 )와 AND 연산 type -d.

추가 조치는 -o print바로 인쇄하는 것입니다.


89
흠. 출력에 무시 된 디렉토리 "./misc"가 포함되어 있기 때문에 나에게도 효과가 없다.
Theuni

84
@Theuni 당신은 -print명시 적으로 뒤에 (또는 다른 조치)를 추가하지 않았기 때문에 아마 당신에게 효과가 없었습니다 -name. 이 경우 -o엔드 업 인쇄 의 두 "면"은 모두 사용하지만을 사용 -print하면 해당 면만 인쇄됩니다.
Daniel C. Sobral

4
맨 페이지에서 : Because -delete implies -depth, you cannot usefully use -prune and -delete together.그렇다면 삭제에서 특정 디렉토리를 제외하려면 find로 삭제하는 방법은 무엇입니까?
Jānis Elmeris

15
결과에서 전체 디렉토리 자체를 제거하려면 다음을 사용하십시오 find . -not -path "./.git*". ./dir*대신에 사용하면 ./dir/*출력 내용에서 디렉토리와 내용 이 제거됩니다.
micahblu

64
이 질문과 답변의 혼동은 찾기 사용자 인터페이스가 사람들이 필요로하는 것에 얼마나 나쁘게 일치하는지에 대한 명백한 것입니다.
Johannes Overmann

1931

-prune당신을 위해 작동하지 않는 경우 :

find -name "*.js" -not -path "./directory/*"

주의 사항 : 원치 않는 모든 디렉토리를 통과해야합니다.


86
허용 된 답변의 의견 중 하나가 문제를 지적합니다. -prune디렉토리 자체를 제외하지 않고 컨텐츠를 제외합니다. 즉, 제외 된 디렉토리의 출력에 원하지 않는 행이 표시됩니다.
GetFree

95
좋은 대답입니다. 이것에 추가하여 첫 번째 .를 로 변경하여 모든 수준에서 디렉토리를 제외시킬 수 있습니다 *. 그래서 find -name "*.js" -not -path "*/omitme/*"깊이의 모든 수준에서 "omitme"라는 이름의 디렉토리에서 파일을 생략 할 것이다.
DeeDee

83
그래도 여전히 원치 않는 모든 디렉토리를 통과 합니다. 내 자신의 답변을 추가하고 있습니다. :-)
Daniel C. Sobral

18
그러나 prune 옵션은 -print명시 적으로 사용하지 않으면 작동하지 않습니다 .
Daniel C. Sobral

39
"-prune 사용에 대한 대안"이라고 말하는 것이 좋습니다. 자두를 암시하는 대답은 분명히 틀린 것이 아니며, 단지 당신이 그렇게하는 방식이 아닙니다.
Jimbo

458

다른 제안 된 솔루션보다 다음과 같이 추론하기가 더 쉽습니다.

find build -not \( -path build/external -prune \) -name \*.js
# you can also exclude multiple paths
find build -not \( -path build/external -prune \) -not \( -path build/blog -prune \) -name \*.js

중요 참고 : 입력 한 경로 는 제외없이 인쇄 할 경로 -path와 정확히 일치해야합니다 find. 이 문장이 혼동되면 다음 과 같이 전체 명령을 통해 전체 경로를 사용해야 합니다. 더 잘 이해하려면 참고 [1]을 참조하십시오.find /full/path/ -not \( -path /full/path/exclude/this -prune \) ...

내부 \(\)일치 표현이다 정확하게 build/external (위의 중요 사항 참조)과 의지, 성공, 아래 피하기 이송 아무것도 . 이것은 다음 탈출 괄호와 하나의 표현으로 그룹화하고,로 시작되고 -not있는 것 find그 표현에 의해 일치 된 건너 뛰기 아무것도.

추가 -not하면 다른 모든 파일이 -prune다시 나타나지 않도록 숨길 수 없는지 물을 수 있으며 대답은 아니오입니다. 방법의 -prune작품이 도달하면 해당 디렉토리 아래의 파일이 영구적으로 무시되고, 그 무엇이다.

이것은 실제 사용 사례에서 나온 것입니다. 여기에는 wintersmith가 생성 한 일부 파일에서 yui 압축기를 호출해야하지만 그대로 보내야하는 다른 파일은 제외하십시오.


참고 [1] : 제외 /tmp/foo/bar하고이 " find /tmp \(..." 와 같이 찾기를 실행 하려면을 지정해야합니다 -path /tmp/foo/bar. 반면에 cd /tmp; find . \(...다음 과 같이 찾은 경우을 지정해야합니다 -path ./foo/bar.


37
탁월한 답변, 감사합니다. 이것은 여러 제외를 위해 확장 가능하고 읽을 수 있습니다. 당신은 신사이자 학자입니다. 여러 제외에 대한 예를 들어 주셔서 감사합니다
Freedom_Ben

7
-delete 스위치를 사용하려면 작동하지 않습니다.find . -not \( -path ./CVS -prune \) -type f -mtime +100 -delete find: The -delete action atomatically turns on -depth, but -prune does nothing when -depth is in effect. If you want to carry on anyway, just explicitly use the -depth option.
Jānis Elmeris

17
@Janis -exec rm -rf {} \;대신 사용할 수 있습니다 -delete.
Daniel C. Sobral

11
의 출력을 검토하면 find실제로 분명하지만 나에게 넘어졌습니다. 현재 디렉토리 .에서 검색 하는 경우 (검색 경로를 지정하거나 전혀 지정하지 않음) 다음 -path과 같이 시작한 후에 패턴을 원할 것입니다 ( ./예 :) find -not \( -path ./.git -prune \) -type f.
Zantier

7
이 방법의보다 정확하고 POSIX 호환 변형 : find searchdir \! \( -type d \( -path './excludedir/*' -o -path './excludedir2/*' -o -path './excludedir3/*' \) -prune \)찾고자하는 것과 일치하는 조건이 뒤 따릅니다.
Walf

217

디렉토리를 건너 뛰기 위해 선호하는 구문이 무엇인지에 대한 혼동이 분명히 있습니다.

GNU 의견

To ignore a directory and the files under it, use -prune

GNU find 맨 페이지에서

추리

-prunefind디렉토리로 내려 가지 않습니다 . 지정 -not -path하면 여전히 건너 뛴 디렉토리 로 내려가 지만 각 파일을 테스트 -not -path할 때마다 false find입니다.

문제 -prune

-prune 의도 한대로 작동하지만 여전히 사용시주의해야 할 사항입니다.

  1. find 정리 된 디렉토리를 인쇄합니다.

    • TRUE 그것은 의도 된 행동이며, 단지 그것에 내려 가지 않습니다. 디렉토리를 모두 인쇄하지 않으려면 논리적으로 생략하는 구문을 사용하십시오.
  2. -prune-print다른 작업 에서만 작동 하고 다른 작업은 수행하지 않습니다.

    • 사실이 아닙니다 . -prune를 제외한 모든 작업에서 작동합니다 -delete. 삭제와 함께 작동하지 않는 이유는 무엇입니까? 들어 -delete작업에 이후, DFS 순서로 디렉토리를 통과 할 필요를 찾아 -delete먼저 ...하지만 지정하기위한, 잎, 잎 등의 후 부모를 삭제 -prune, 메이크업 감각에 find그것을 내려 디렉토리 및 정지를 칠 요구를하는 분명히 -depth또는 말로 의미가 없습니다 -delete.

공연

나는 (대체이 질문에 3 대 upvoted 답변 간단한 테스트를 설정 -print하여 -exec bash -c 'echo $0' {} \;다른 동작의 예를 보여). 결과는 다음과 같습니다

----------------------------------------------
# of files/dirs in level one directories
.performance_test/prune_me     702702    
.performance_test/other        2         
----------------------------------------------

> find ".performance_test" -path ".performance_test/prune_me" -prune -o -exec bash -c 'echo "$0"' {} \;
.performance_test
.performance_test/other
.performance_test/other/foo
  [# of files] 3 [Runtime(ns)] 23513814

> find ".performance_test" -not \( -path ".performance_test/prune_me" -prune \) -exec bash -c 'echo "$0"' {} \;
.performance_test
.performance_test/other
.performance_test/other/foo
  [# of files] 3 [Runtime(ns)] 10670141

> find ".performance_test" -not -path ".performance_test/prune_me*" -exec bash -c 'echo "$0"' {} \;
.performance_test
.performance_test/other
.performance_test/other/foo
  [# of files] 3 [Runtime(ns)] 864843145

결론

f10bit의 구문다니엘 C. 소브랄의 구문은 평균 실행 10-25ms했다. 사용하지 않는 GetFree의 구문-prune 은 865ms가 걸렸습니다. 예, 이것은 다소 극단적 인 예이지만 런타임에 관심이 있고 원격으로 집중적 인 작업을 수행하는 경우을 사용해야합니다 -prune.

참고 Daniel C. Sobral의 구문 은 두 -prune구문 중 더 나은 성능을 나타 냈습니다. 그러나 나는 이것이 두 가지 실행 결과가 반대 결과를 초래하는 순서를 전환하여 일부 캐싱의 결과라고 생각합니다.

테스트 스크립트

#!/bin/bash

dir='.performance_test'

setup() {
  mkdir "$dir" || exit 1
  mkdir -p "$dir/prune_me/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/w/x/y/z" \
    "$dir/other"

  find "$dir/prune_me" -depth -type d -exec mkdir '{}'/{A..Z} \;
  find "$dir/prune_me" -type d -exec touch '{}'/{1..1000} \;
  touch "$dir/other/foo"
}

cleanup() {
  rm -rf "$dir"
}

stats() {
  for file in "$dir"/*; do
    if [[ -d "$file" ]]; then
      count=$(find "$file" | wc -l)
      printf "%-30s %-10s\n" "$file" "$count"
    fi
  done
}

name1() {
  find "$dir" -path "$dir/prune_me" -prune -o -exec bash -c 'echo "$0"'  {} \;
}

name2() {
  find "$dir" -not \( -path "$dir/prune_me" -prune \) -exec bash -c 'echo "$0"' {} \;
}

name3() {
  find "$dir" -not -path "$dir/prune_me*" -exec bash -c 'echo "$0"' {} \;
}

printf "Setting up test files...\n\n"
setup
echo "----------------------------------------------"
echo "# of files/dirs in level one directories"
stats | sort -k 2 -n -r
echo "----------------------------------------------"

printf "\nRunning performance test...\n\n"

echo \> find \""$dir"\" -path \""$dir/prune_me"\" -prune -o -exec bash -c \'echo \"\$0\"\'  {} \\\;
name1
s=$(date +%s%N)
name1_num=$(name1 | wc -l)
e=$(date +%s%N)
name1_perf=$((e-s))
printf "  [# of files] $name1_num [Runtime(ns)] $name1_perf\n\n"

echo \> find \""$dir"\" -not \\\( -path \""$dir/prune_me"\" -prune \\\) -exec bash -c \'echo \"\$0\"\' {} \\\;
name2
s=$(date +%s%N)
name2_num=$(name2 | wc -l)
e=$(date +%s%N)
name2_perf=$((e-s))
printf "  [# of files] $name2_num [Runtime(ns)] $name2_perf\n\n"

echo \> find \""$dir"\" -not -path \""$dir/prune_me*"\" -exec bash -c \'echo \"\$0\"\' {} \\\;
name3
s=$(date +%s%N)
name3_num=$(name3 | wc -l)
e=$(date +%s%N)
name3_perf=$((e-s))
printf "  [# of files] $name3_num [Runtime(ns)] $name3_perf\n\n"

echo "Cleaning up test files..."
cleanup

18
좋은 분석 감사합니다. "일부 캐싱의 결과라고 생각합니다"와 관련하여 다음 명령을 실행할 수 있습니다. sudo sh -c "free && sync && echo 3> / proc / sys / vm / drop_caches && free"캐시를 지우십시오 ( 유닉스 참조) . stackexchange.com/questions/87908/… ).
ndemou

그 두 가지에 대한 몇 가지 테스트 후에 -prune거의 차이가 없음을 알 수 있습니다. , 나중에 명령은 CPU 성능 도움이됩니다 처음 시작하는 것을 염두에 두어야을 마십시오 CPU가 워밍업> 성능 저하의 원인이 사소한 천천히 아래로 (나는 @ndemou 제안 각 명령 앞에 퍼지 캐시를했다)
Huy.PhamNhu

name1() name2() name3()위의 @BroSlow 테스트 스크립트 중 스위치 번호 를 사용하여 실행 순서를 변경하여 내가 말한 것에 대한 시각적 정보를 얻으십시오. 실생활에서는이 둘 사이에서 눈에 띄지 않습니다.
Huy.PhamNhu

박수 갈채. 이 품질 답변에 감사드립니다.
Stphane

또는를 의미하는 -o가되어서는 안됩니다. 첫 번째 단계에서 잘라 내고 다음 단계에서 모든 것을 잊어 버립니다.
mmm

96

이것은 나를 위해 일한 유일한 것입니다.

find / -name MyFile ! -path '*/Directory/*'

"디렉토리"를 제외한 "MyFile"을 검색합니다. 별에 중점을 둡니다 *.


13
이 방법은 macOS에서 작동하지만 허용되는 답변은 그렇지 않습니다. 원래 질문은 Linux에 대한 것임을 알고 있습니다.
Xavier Rubio Jansana

5
! -path '*/Directory/*'여러 디렉토리를 무시하기 위해 명령에 여러 개 를 연속으로 추가 할 수 있습니다.
Aclwitt

MacOS에서는 작동하지만 리눅스에서는 작동하지 않습니다 ... 확인
Marcello de Sales

A의 docker container경우에만 작동sh -c "find..."
마르첼로 드 판매

@Marcello de Sales 물론 Linux에서 작동합니다.
DimiDak

59

하나의 옵션은 grep을 가진 디렉토리 이름이 포함 된 모든 결과를 제외하는 것입니다. 예를 들면 다음과 같습니다.

find . -name '*.js' | grep -v excludeddir

44
이렇게하면 검색 속도가 매우 느려집니다
Dorian

6
이것은 나를 위해 일했지만 다른 사람들은 (를 사용하는 -prune)-하지 않았습니다.
Andron

7
큰 결과는 느리지 만 작은 세트에는 유용합니다. 그러나 grep을 사용하여 여러 디렉토리를 제외시키는 방법은 무엇입니까? 물론이 방법 : find . -name '*.js' | grep -v excludeddir | grep -v excludedir2 | grep -v excludedir3그러나 하나의 grep 방법이있을 수 있습니다.
Timo Kähkönen

6
여러 그렙을 수행하려면 정규 표현식으로 작성하는 것이 좋습니다 egrep -v '(dir1|dir2|dir3)'. 그러나이 특정 사례 연구에서는 디렉토리 find자체 를 제외하는 것이 좋습니다 .
Laurence

1
예, 괄호가 필요하지 않으며 ^를 사용하여 문자열 시작시 directoryname과 일치하는지 확인하는 것이 좋습니다 (예 : find). -name '* .js'| egrep -v "^ \ ./ excludeddir1 | ^ \ ./ excludeddir2"
Sofija

41

나는 -not표기법을 선호합니다 ... 더 읽기 쉽습니다.

find . -name '*.js' -and -not -path directory

5
죄송합니다. 작동하지 않습니다. 매뉴얼 페이지에 find"디렉토리와 그 파일을 무시하려면 -prune을 사용하십시오"라고 나와 있습니다.
Christian Davén

8
이것은 잘못이다. find가 디렉토리에 들어가서 모든 파일을 탐색하는 것을 막지는 않습니다.
GetFree

find . -iname '*' -and -not -path './somePath'해당 디렉토리에 들어가는 것을 막지 않습니다.
Lemmings19

이것은 .git path를 도와주었습니다 find . -iname '*' -not -path './.git/*'
Mark Shust at M.academy

7
@rane : 더 구체적으로 find . -not -path "*/.git*"당신이 원하는 것입니다.

20

-prune 옵션을 사용하십시오. 따라서 다음과 같은 것이 있습니다.

find . -type d -name proc -prune -o -name '*.js'

'-type d -name proc -prune'은 제외 할 proc라는 디렉토리 만 찾습니다.
'-o'는 'OR'연산자입니다.


1
이것은 나를 위해 일한 유일한 순수한 "찾기"솔루션입니다. 제외하려는 디렉토리가 현재 작업 디렉토리 바로 아래에 있지 않습니다.
Lambart

5
그러나 -print끝에 추가 하면 결과가 향상 될 수 있습니다. find . -type d -name .hg -prune -o -name data(다중) .hg디렉토리 의 내용을 무시 했지만 .hg디렉토리 자체를 나열 했습니다. 로 -print, 내가 찾던 "data"디렉토리 만 나열했습니다.
Lambart

19

-prune확실히 작동하고 제외하려는 디렉토리로 내려 가지 않기 때문에 가장 좋은 대답입니다. -not -path여전히 제외 된 디렉토리를 검색하면 결과를 인쇄하지 않으므로 제외 된 디렉토리가 네트워크 볼륨에 마운트되어 있거나 권한이없는 경우 문제가 될 수 있습니다.

까다로운 부분은 find인수의 순서가 매우 중요 하다는 것입니다. 따라서 인수를 올바르게하지 않으면 명령이 작동하지 않을 수 있습니다. 인수 순서는 일반적으로 다음과 같습니다.

find {path} {options} {action}

{path}: 모든 경로 관련 인수를 먼저 입력하십시오. . -path './dir1' -prune -o

{options}: -name, -iname, etc이 그룹의 마지막 옵션으로 가장 성공했습니다 . 예 :-type f -iname '*.js'

{action}: -print사용할 때 추가하고 싶습니다-prune

다음은 실제 예입니다.

# setup test
mkdir dir1 dir2 dir3
touch dir1/file.txt; touch dir1/file.js
touch dir2/file.txt; touch dir2/file.js
touch dir3/file.txt; touch dir3/file.js

# search for *.js, exclude dir1
find . -path './dir1' -prune -o -type f -iname '*.js' -print

# search for *.js, exclude dir1 and dir2
find . \( -path './dir1' -o -path './dir2' \) -prune -o -type f -iname '*.js' -print

16

이것은 일부 경로를 제외하는 데 사용한 형식입니다.

$ find ./ -type f -name "pattern" ! -path "excluded path" ! -path "excluded path"

". *"경로에없는 모든 파일을 찾기 위해 이것을 사용했습니다.

$ find ./ -type f -name "*" ! -path "./.*" ! -path "./*/.*"

나는 이것을 시도했지만 여전히 디렉토리로 내려가므로 속도는 확실히 향상되지 않습니다.
Br.Bill

10

-path -prune 접근법은 경로의 와일드 카드와도 작동합니다. 다음은 git 내부 디렉토리를 제외하고 여러 git 리포지토리를 제공하는 git 서버의 디렉토리를 찾는 find 문입니다.

find . -type d \
   -not \( -path */objects -prune \) \
   -not \( -path */branches -prune \) \
   -not \( -path */refs -prune \) \
   -not \( -path */logs -prune \) \
   -not \( -path */.git -prune \) \
   -not \( -path */info -prune \) \
   -not \( -path */hooks -prune \)  

9

여러 디렉토리를 제외하려면 다음을 수행하십시오.

find . -name '*.js' -not \( -path "./dir1" -o -path "./dir2/*" \)

디렉토리를 추가하려면 다음을 추가하십시오 -o -path "./dirname/*".

find . -name '*.js' -not \( -path "./dir1" -o -path "./dir2/*" -o -path "./dir3/*"\)

그러나 제외 할 디렉토리가 많은 경우 정규식 을 사용해야합니다 .


9

좋은 대답이 많이 있습니다. 명령의 각 요소가 무엇인지, 그 논리를 이해하는 데 시간이 걸렸습니다.

find . -path ./misc -prune -o -name '*.txt' -print

find는 현재 디렉토리에서 파일과 디렉토리를 찾기 시작합니다 find ..

-o옵션은 논리 OR을 나타내며 명령의 두 부분을 구분합니다.

[ -path ./misc -prune ] OR [ -name '*.txt' -print ]

어떤 디렉토리 나 파일 하지 ./misc 디렉토리는 첫 번째 테스트를 통과하지 않습니다 -path ./misc. 그러나 그들은 두 번째 표현에 대해 테스트됩니다. 해당 이름 *.txt-print옵션으로 인해 인쇄 된 패턴과 일치하는 경우

find가 ./misc 디렉토리에 도달하면이 디렉토리는 첫 번째 표현식 만 만족시킵니다. 따라서 -prune옵션이 적용됩니다. find 명령이 해당 디렉토리를 탐색 하지 않도록 지시합니다 . 따라서 ./misc의 파일이나 디렉토리는 find로 탐색되지 않으며 표현식의 두 번째 부분에 대해 테스트되지 않으며 인쇄되지 않습니다.


모두에게 해결책이 있지만 최선의 방법을 설명했습니다. 나는 -path 대신에 -name을 먼저 사용하도록 단호했다. 당신의 설명은 내가 원하는 것에 도달하기에 충분했습니다. 찾기 . -name "* .txt"-print -o -path ./misc -prune
Vendetta V

7

작동 솔루션 (Ubuntu 12.04 (Precise Pangolin)에서 테스트) ...

find ! -path "dir1" -iname "*.mp3"

dir1 하위 폴더를 제외한 현재 폴더 및 하위 폴더에서 MP3 파일을 검색합니다.

사용하다:

find ! -path "dir1" ! -path "dir2" -iname "*.mp3"

... dir1과 dir2를 제외하려면


나를 위해 작동하지 않습니다. 위의 답변 중 어느 것도 수행하지 마십시오. 빨간 모자.
Tharpa

6

제거 된 디렉토리를 인쇄 피하기위한 좋은 트릭을 사용하는 것입니다 -print(에 대한 작품 -exec의 오른쪽 측면 후뿐만 아니라) -or-prune. 예를 들어 ...

find . -path "*/.*" -prune -or -iname "*.j2"

".j2"확장자로 현재 디렉토리 아래에있는 모든 파일의 경로를 인쇄하고 숨겨진 모든 디렉토리를 건너 뛰지 만 깔끔한 것입니다. 그러나 위에서 언급 한 것처럼 건너 뛴 각 디렉토리의 전체 경로를 인쇄합니다. 다음은 그렇지 않습니다 ...

find . -path "*/.*" -prune -or -iname "*.j2" -print

논리적으로 연산자 -and뒤에 -iname그리고 -print 앞에 숨겨져 있기 때문 입니다. -or부울 연산 순서 및 연관성으로 인해 절의 오른쪽 부분에 바인딩됩니다 . 그러나 문서 는 그것이 지정되어 있지 않으면 숨겨진 -print것이 있다고 말합니다 -print0. 왜 -or인쇄 의 왼쪽 부분이 아닌가? 분명히 (그리고 맨 처음 읽는 페이지에서 이것을 이해하지 못했습니다), -print-또는 아무 곳에도없는 경우 사실 -exec입니다.이 경우 -print가 논리적으로 뿌려져 모든 것이 인쇄됩니다. 하나라도print스타일 연산은 모든 절에서 표현되며 숨겨진 모든 논리 연산은 사라지고 지정한 것만 얻습니다. 솔직히 말해서, 다른 방법으로 선호했을 수도 있지만find설명 연산자 만 있으면 아무것도하지 않을 것이므로 그대로 이해하는 것 같습니다. 위에서 언급했듯이 이것도 모두 작동 -exec하므로 다음은 ls -la원하는 확장자를 가진 각 파일에 대한 전체 목록을 제공 하지만 각 숨겨진 디렉토리의 첫 번째 수준은 나열하지 않습니다 ...

find . -path "*/.*" -prune -or -iname "*.j2" -exec ls -la -- {} +

나 (그리고이 스레드의 다른 사람들)에게 find구문은 꽤 빨리 빠릅니다. 그래서 나는 항상 무엇을 바인딩하는지 알기 위해 항상 괄호를 던집니다. ..

find . \( \( ... description of stuff to avoid ... \) -prune \) -or \
\( ... description of stuff I want to find ... [ -exec or -print] \)

이런 식으로 세계를 두 부분으로 설정하면 잘못되기가 어렵습니다. 누군가가 30 번째 이상의 답변을 읽고 투표하기는 쉽지 않지만 희망이 있습니다. :-)


5

제거 옵션을 사용하여이를 수행 할 수 있습니다. 예를 들어

find ./ -path ./beta/* -prune -o -iname example.com -print

또는 반대 grep“grep -v”옵션 :

find -iname example.com | grep -v beta

Linux find 명령 exclude directorys에서 검색 에 대한 자세한 지침과 예제를 찾을 수 있습니다 .


grep 솔루션은 동일한 이름으로 모든 디렉토리를 제외하는 유일한 솔루션입니다. "node_modules"를 제외하려고 할 때 매우 유용합니다.
bmacnaughton

3
@bmacnaughton-사실이 아닙니다! 나는 특별히 "node_modules"를 배제하기 위해 여기에 왔으며 많은 훌륭한 답변을 읽은 후에는 find . -type f -print -o -path "*/node_modules" -prune... 와일드 카드를 사용하여 모든 레벨에서 "node_modules"를 건너 뜁니다. 사용하여 -print첫 번째 대안에 -type f -print일부 인쇄는은 "node_modules"디렉토리 그래서 자신이 나열되지 않은 것만 있습니다. (그것은 또한 반전 할 수 있습니다 find . -path "*/node_modules" -prune -o -type f -print)
스티븐 P에게

거기에서 무엇을하고 있습니까? 제외하려는 정확한 파일은 무엇입니까? YPU는 와일드 카드로 사용하고 있습니까?
시주 V

1
@StephenP, 이것을 지적 해 주셔서 감사합니다. 나는 그것 ./node_modules*/node_modules그것 의 차이점을 배웠다 . 필자의 경우, node_modules검색을 시작하는 디렉토리 (및 해당 node_modules디렉토리 아래 ) 에만 존재 find . -type f -print -o -path "./node_modules" -prune 하는 node_modules경우 다른 디렉토리 아래 에 디렉토리 가 없기 때문에 사용할 수 있습니다 .
bmacnaughton

1
@SijuV-내가 검색 한 node_modules디렉토리에 하위 디렉토리가 있었지만 자체 node_modules 가있는 하위 디렉토리도있었습니다 ... using 현재 디렉토리 아래의 ./node_modules하위 디렉토리 만 일치하고 정리 합니다. 사용하여 (가) 때문에, 어떤 깊이에 일치와 자두에게 디렉토리를 A와 글로브 선행 경로 접두사와 일치 같은 뿐만 아니라 접두사. 는 와일드 카드이지만, 글로브로하지 정규식있다. node_modules.*/node_modules*./test5/main/node_modules./*
Stephen P

5
find . -name '*.js' -\! -name 'glob-for-excluded-dir' -prune

이 기능을 작동시킬 수 없습니다. find ~/Projects -name '*.js' -\! -name 'node_modules' -prunenode_modules
mpen

1
@mpen, stackoverflow.com/questions/4210042/…에서 , 나는 당신이 원하는 구문이 있다는 것을 배웠습니다 find ~/Projects -path ~/Projects/node_modules -prune -o -name '*.js' -print. 해당 경로의 이름은 디렉토리를 인쇄하려는 경우 find가 인쇄 할 것과 정확히 일치해야합니다.
PatS

4
find -name '*.js' -not -path './node_modules/*' -not -path './vendor/*'

같은 작동하는 것 같습니다

find -name '*.js' -not \( -path './node_modules/*' -o -path './vendor/*' \)

IMO를 기억하기가 더 쉽습니다.


4

TLDR : 루트 디렉토리를 이해하고 -path <excluded_path> -prune -o옵션을 사용하여 검색을 조정하십시오 . /제외 된 경로의 끝에 후행 을 포함하지 마십시오 .

예:

find / -path /mnt -prune -o -name "*libname-server-2.a*" -print


효과적으로 사용하려면 find파일 시스템 디렉토리 구조를 잘 이해해야합니다. 가정용 컴퓨터에는 멀티 TB 하드 드라이브가 있으며 그 중 절반은 rsnapshot(예 :)를 사용하여 백업됩니다 rsync. 물리적으로 독립적 인 (중복) 드라이브로 백업하지만 시스템 루트 ( /) 디렉토리에 마운트됩니다 . /mnt/Backups/rsnapshot_backups/:

/mnt/Backups/
└── rsnapshot_backups/
    ├── hourly.0/
    ├── hourly.1/
    ├── ...
    ├── daily.0/
    ├── daily.1/
    ├── ...
    ├── weekly.0/
    ├── weekly.1/
    ├── ...
    ├── monthly.0/
    ├── monthly.1/
    └── ...

/mnt/Backups/rsnapshot_backups/디렉토리는 현재 60M 파일 및 폴더 ~와 함께, ~ 2.9 TB를 차지; 해당 내용을 순회하는 데 시간이 걸립니다.

## As sudo (#), to avoid numerous "Permission denied" warnings:

time find /mnt/Backups/rsnapshot_backups | wc -l
60314138    ## 60.3M files, folders
34:07.30    ## 34 min

time du /mnt/Backups/rsnapshot_backups -d 0
3112240160  /mnt/Backups/rsnapshot_backups    ## 3.1 TB
33:51.88    ## 34 min

time rsnapshot du    ## << more accurate re: rsnapshot footprint
2.9T    /mnt/Backups/rsnapshot_backups/hourly.0/
4.1G    /mnt/Backups/rsnapshot_backups/hourly.1/
...
4.7G    /mnt/Backups/rsnapshot_backups/weekly.3/
2.9T    total    ## 2.9 TB, per sudo rsnapshot du (more accurate)
2:34:54          ## 2 hr 35 min

따라서 /(루트) 파티션에서 파일을 검색해야 할 때마다 백업 파티션 통과를 처리해야합니다 (가능한 경우 피하십시오).


실시 예

이 스레드에서 다양하게 제안 된 접근법 중 ( find. 명령에서 디렉토리를 제외하는 방법 ), 나는 받아 들여진 대답을 사용하는 검색 이주의를 기울 이면 훨씬 빠릅니다.

해결책 1

시스템 파일을 찾고 libname-server-2.a싶지만 rsnapshot백업 을 검색하고 싶지 않다고 가정 해 봅시다 . 시스템 파일을 빨리 찾으려면 제외 경로를 사용하십시오 /mnt(예 : /mnt, not /mnt/, 또는 /mnt/Backups, 또는 ... 사용).

## As sudo (#), to avoid numerous "Permission denied" warnings:

time find / -path /mnt -prune -o -name "*libname-server-2.a*" -print
/usr/lib/libname-server-2.a
real    0m8.644s              ## 8.6 sec  <<< NOTE!
user    0m1.669s
 sys    0m2.466s

## As regular user (victoria); I also use an alternate timing mechanism, as
## here I am using 2>/dev/null to suppress "Permission denied" warnings:

$ START="$(date +"%s")" && find 2>/dev/null / -path /mnt -prune -o \
    -name "*libname-server-2.a*" -print; END="$(date +"%s")"; \
    TIME="$((END - START))"; printf 'find command took %s sec\n' "$TIME"
/usr/lib/libname-server-2.a
find command took 3 sec     ## ~3 sec  <<< NOTE!

... 발견이 단 몇 초 파일이 걸릴는 동안 이상 (이하 "제외"모든 디렉토리를 재귀 것처럼 보이는) :

## As sudo (#), to avoid numerous "Permission denied" warnings:

time find / -path /mnt/ -prune -o -name "*libname-server-2.a*" -print
find: warning: -path /mnt/ will not match anything because it ends with /.
/usr/lib/libname-server-2.a
real    33m10.658s            ## 33 min 11 sec (~231-663x slower!)
user    1m43.142s
 sys    2m22.666s

## As regular user (victoria); I also use an alternate timing mechanism, as
## here I am using 2>/dev/null to suppress "Permission denied" warnings:

$ START="$(date +"%s")" && find 2>/dev/null / -path /mnt/ -prune -o \
    -name "*libname-server-2.a*" -print; END="$(date +"%s")"; \
    TIME="$((END - START))"; printf 'find command took %s sec\n' "$TIME"
/usr/lib/libname-server-2.a
find command took 1775 sec    ## 29.6 min

해결책 2

이 스레드에서 제공되는 다른 솔루션 ( SO # 4210042 )도 성능이 좋지 않습니다.

## As sudo (#), to avoid numerous "Permission denied" warnings:

time find / -name "*libname-server-2.a*" -not -path "/mnt"
/usr/lib/libname-server-2.a
real    33m37.911s            ## 33 min 38 sec (~235x slower)
user    1m45.134s
 sys    2m31.846s

time find / -name "*libname-server-2.a*" -not -path "/mnt/*"
/usr/lib/libname-server-2.a
real    33m11.208s            ## 33 min 11 sec
user    1m22.185s
 sys    2m29.962s

요약 | 결론

" 솔루션 1 "에 설명 된 방법을 사용하십시오.

find / -path /mnt -prune -o -name "*libname-server-2.a*" -print

... -path <excluded_path> -prune -o ...

/제외 경로에 후행 을 추가 할 때마다 find명령은 모든 /mnt/*디렉토리 를 재귀 적으로 입력합니다.이 경우 /mnt/Backups/rsnapshot_backups/*하위 디렉토리로 인해 검색 할 파일이 ~ 2.9TB가 추가됩니다! 후행을 추가하지 않으면 /검색이 거의 즉시 완료됩니다 (초 이내).

... -not -path <exclude path> ...마찬가지로 "솔루션 2"( )도 제외 된 디렉토리를 통해 재귀 적으로 검색하는 것으로 보입니다. 제외 된 일치 항목을 반환하지 않고 해당 검색 시간을 불필요하게 소비합니다.


그 안에서 검색 rsnapshot 백업 :

시간별 / 일별 / 주별 / 월별 rsnapshot백업 중 하나에서 파일을 찾으려면 ) :

$ START="$(date +"%s")" && find 2>/dev/null /mnt/Backups/rsnapshot_backups/daily.0 -name '*04t8ugijrlkj.jpg'; END="$(date +"%s")"; TIME="$((END - START))"; printf 'find command took %s sec\n' "$TIME"
/mnt/Backups/rsnapshot_backups/daily.0/snapshot_root/mnt/Vancouver/temp/04t8ugijrlkj.jpg
find command took 312 sec   ## 5.2 minutes: despite apparent rsnapshot size
                            ## (~4 GB), it is in fact searching through ~2.9 TB)

중첩 된 디렉토리 제외 :

여기에서 /mnt/Vancouver/projects/ie/claws/data/*검색 할 때 중첩 된 디렉토리를 제외하고 싶습니다 /mnt/Vancouver/projects/.

$ time find . -iname '*test_file*'
./ie/claws/data/test_file
./ie/claws/test_file
0:01.97

$ time find . -path '*/data' -prune -o -iname '*test_file*' -print
./ie/claws/test_file
0:00.07

옆으로 :-print 명령 끝에 추가 하면 제외 된 디렉토리의 출력이 억제됩니다.

$ find / -path /mnt -prune -o -name "*libname-server-2.a*"
/mnt
/usr/lib/libname-server-2.a

$ find / -path /mnt -prune -o -name "*libname-server-2.a*" -print
/usr/lib/libname-server-2.a

속도가 느린 파일의 크기가 아니라 검사해야하는 디렉토리 항목find수입니다 . 따라서 몇 개의 작은 기가 바이트 파일을 가지고있는 것보다 많은 작은 파일 (특히 모두가 여러 개가 연결된 경우)이 많은 경우 훨씬 더 나쁩니다.
Toby Speight

@TobySpeight : 좋은 지적입니다. 검색 공간 크기를 언급하여 스케일을 나타내며 많은 파일이 포함되어 있습니다. 로 루트 (/)를 빠르게 검색하면 sudo ls -R / | wc -l~ 76.5M 파일 을 나타냅니다 (대부분은 "비 구성"시스템 파일을 제외하고 백업됩니다). /mnt/Vancouver/with ls -R | wc -l는 ~ 2.35M 파일 을 나타냅니다. /home/victoria/0.668M 파일을 포함합니다.
빅토리아 스튜어트

4

정규식을 사용하여 다음과 같은 방법으로 일부 파일을 포함 / 제외 할 수 있습니다.

find . -regextype posix-egrep -regex ".*\.(js|vue|s?css|php|html|json)$" -and -not -regex ".*/(node_modules|vendor)/.*" 

이렇게하면 모든 js, vue, css 등의 파일 만 제공되지만 node_modulesvendor폴더의 모든 파일은 제외됩니다 .


3

find대한 파일 목록을 제공하는 데 사용 xgettext하고 특정 디렉토리와 해당 내용을 생략하고 싶었습니다. 나는 많은 순열을 -path결합 하려고 시도했지만 -prune원하는 디렉토리를 완전히 제외시킬 수 없었습니다.

무시하려는 디렉토리 의 내용 을 무시할 수 있었지만 find디렉토리 자체를 결과 중 하나로 반환했습니다.xgettext 로 충돌했습니다 (디렉토리를 허용하지 않고 파일 만).

내 솔루션은 단순히 grep -v결과에서 원하지 않는 디렉토리를 건너 뛰는 데 사용 하는 것이 었습니다 .

find /project/directory -iname '*.php' -or -iname '*.phtml' | grep -iv '/some/directory' | xargs xgettext

find100 % 효과가있을 것이라는 주장이 있든 없든 나는 확실히 말할 수 없다. grep두통이 발생한 후 사용하는 것이 빠르고 쉬운 해결책이었습니다.


3

이전 답변 중 우분투에는 좋지 않습니다. 이 시도:

find . ! -path "*/test/*" -type f -name "*.js" ! -name "*-min-*" ! -name "*console*"

나는 이것을 여기 에서 찾았다


100 점 이상의 답변이 Ubuntu에서 작동하지 않는 이유는 없습니다.
Axel Beckert

보자? 어쩌면 내가 그들 모두를 시도했기 때문에?
sixro

find는 모든 Linux 배포판에서 GNU 프로젝트의 배포판에서 동일하게 구현됩니다. 유일한 차이점은 버전 일 수 있습니다. 그러나 지난 10 년간의 변화는 권한 일치를 제외하고는 침습적이지 않았습니다.
Axel Beckert

3

이것은 Mac에서 나에게 적합합니다.

find . -name *.php -or -path "./vendor" -prune -or -path "./app/cache" -prune

접미사가 붙은 검색 이름 은 제외 vendor하고 app/cachedir입니다 php.


'* .php'주위에 작은 따옴표를 두는 것이 좋습니다. 그렇지 않으면 원하는 것을 찾지 못할 것입니다.
Br.Bill

3

-path 또는 -not을 사용할 수없는 이전 버전의 UNIX 사용자

SunOS 5.10 bash 3.2 및 SunOS 5.11 bash 4.4에서 테스트

find . -type f -name "*" -o -type d -name "*excluded_directory*" -prune -type f

지정된 디렉토리 이상을 전달할 수 있습니다.
MUY Belgium

2

사용 방법 정리 옵션Laurence Gonsalves 가 어떻게 -prune작동 하는지에 대한 훌륭한 답변 입니다.

그리고 일반적인 해결책은 다음과 같습니다.

find /path/to/search                    \
  -type d                               \
    \( -path /path/to/search/exclude_me \
       -o                               \
       -name exclude_me_too_anywhere    \
     \)                                 \
    -prune                              \
  -o                                    \
  -type f -name '*\.js' -print

/path/to/seach/여러 번 입력하지 않으려면 findpushd .. popd쌍으로 포장하십시오 .

pushd /path/to/search;                  \
find .                                  \
  -type d                               \
    \( -path ./exclude_me               \
       -o                               \
       -name exclude_me_too_anywhere    \
     \)                                 \
    -prune                              \
  -o                                    \
  -type f -name '*\.js' -print;         \
 popd

1
에서 stackoverflow.com/questions/4210042/... , 나는에 사용되는 구문이 사실을 알게 -path그렇게 디렉토리를 인쇄 할 수 있다면 발견 예를 들어, 인쇄 것이라고 이름과 일치해야합니다 find . -path ./.git -prune -o -print, 또는 find $HOME/foo -path $HOME/foo/.git -prune -o -print 답변 중 일부는 단지 말 -path somedir불행히도 인을 유용 할 정도로 정확하지 않습니다.
PatS

2

내가 필요한 것은 landscape.jpg루트에서 시작하여 /var디렉토리 에서 검색을 제외하고 모든 서버에서 다음과 같이 작동했습니다 .

find / -maxdepth 1 -type d | grep -v /var | xargs -I '{}' find '{}' -name landscape.jpg

find / -maxdepth 1 -type d모든 목록 차원 에서 irectories을/

grep -v /var 리스트에서`/ var '를 제외

xargs -I '{}' find '{}' -name landscape.jpgfind각 디렉토리 / 목록의 결과와 같은 명령을 실행 하십시오.


잠깐만, /아직 배제되지 않았습니다. 필요할 수 있습니다 sed 1d.
Simba

2

다음 명령이 작동합니다.

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

찾기에 문제가있는 경우 -D tree옵션을 사용 하여 표현식 분석 정보를보십시오.

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

또는 -D all모든 실행 정보를 보려면.

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

1

C 소스 파일의 함수 이름은 * .o 및 * .swp 및 exclude (일반 파일 아님)를 제외하고 다음 명령으로 dir 출력을 제외합니다.

find .  \( ! -path "./output/*" \) -a \( -type f \) -a \( ! -name '*.o' \) -a \( ! -name '*.swp' \) | xargs grep -n soc_attach

1

루프 exec보다 동작을 더 잘 사용하십시오 for.

find . -path "./dirtoexclude" -prune \
    -o -exec java -jar config/yuicompressor-2.4.2.jar --type js '{}' -o '{}' \;

exec ... '{}' ... '{}' \;중괄호를 교체, 모든 일치하는 파일에 대해 한 번 실행됩니다 '{}'현재 파일 이름.

중괄호는 작은 따옴표로 묶어 쉘 스크립트 문장 부호 * 로 해석되지 않도록합니다 .


노트

*find (GNU findutils) 4.4.2 매뉴얼 페이지 의 예 섹션에서


1
아주 오래된 질문이지만 여전히 개선의 여지가 있습니다. 우연히 비슷한 문제를 해결하려고 시도했지만 만족스러운 답변이 없었습니다.
Alberto

나는 그 exec행동을 자주 사용하고 매우 유용하다고 생각합니다. 나는 일반적으로 {}파일 경로에 공백이있는 경우를 대비 하여 따옴표를 추가합니다 "{}".
Ludovic Kuty

@lkuty 나는 귀하의 의견을 반영하기 위해 게시물을 편집하려고했지만 빠른 테스트 (인용없이 {}파일 이름에 공백이있는 파일에 대해서는 작동합니다)와 매뉴얼 페이지를 살펴본 후에는 인용을 피해야 할 필요가있는 것 같습니다 쉘 스크립트 문장 부호로 잘못 해석됩니다. 이 경우 작은 따옴표를 사용합니다 :'{}'
Alberto

나는 그것을 만들기 위해 사용했다라고 생각 cp하거나 mv또는 rm. 내가 그것을 확인합니다
Ludovic Kuty

1

위의 명령을 시도했지만 "-prune"을 사용하는 사람은 저에게 효과적이지 않습니다. 결국 나는 아래 명령으로 이것을 시도했다.

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