Programing

sh에서 'find'의 '-prune'옵션을 사용하는 방법은 무엇입니까?

lottogame 2020. 5. 6. 20:48
반응형

sh에서 'find'의 '-prune'옵션을 사용하는 방법은 무엇입니까?


나는에서 주어진 예를 이해하지 못합니다. man find누구든지 나에게 몇 가지 예와 설명을 줄 수 있습니까? 정규 표현식을 결합 할 수 있습니까?


더 자세한 질문은 다음과 같습니다.

changeall와 같은 인터페이스를 가진 쉘 스크립트를 작성하십시오 changeall [-r|-R] "string1" "string2". 그것은의 접미사로 모든 파일을 찾을 것입니다 .h, .C, .cc, 또는 .cpp모든 항목 변경 string1에를 string2. -r현재 디렉토리에만 머 무르거나 하위 디렉토리를 포함하는 옵션입니다.

노트:

  1. 재귀 ls가 아닌 경우 허용되지 않으며 find만 사용할 수 있습니다 sed.
  2. 시도 find -depth했지만 지원되지 않았습니다. 그렇기 때문에 -prune도움이 될지 궁금 했지만의 예를 이해하지 못했습니다 man find.

EDIT2 : 과제를하고 있었는데 직접 마무리하고 싶기 때문에 질문을하지 않았습니다. 나는 이미 그것을하고 나눠 주었으므로 이제 모든 질문을 진술 할 수 있습니다. 또한을 사용하지 않고 과제를 완료 -prune했지만 어쨌든 배우고 싶습니다.


내가 혼란스럽게 생각한 것은 테스트 (와 같은 )가 아니라 -prune행동 -print과 같은 것 -name입니다. "할 일"목록을 변경 하지만 항상 true를 반환합니다 .

사용하는 일반적인 패턴 -prune은 다음과 같습니다.

find [path] [conditions to prune] -prune -o \
            [your usual conditions] [actions to perform]

테스트의 첫 부분 (및 최대 포함 )은 실제로 원하는 항목 (예 : 정리 하지 않으려 는 항목)에 대해 false반환 하기 때문에 거의 항상 -o(논리적 OR)을 원합니다 .-prune-prune

예를 들면 다음과 같습니다.

find . -name .snapshot -prune -o -name '*.foo' -print

".snapshot"디렉토리에없는 "* .foo"파일을 찾을 수 있습니다. 이 예에서, -name .snapshot최대하게 [conditions to prune]하고 -name '*.foo' -print있다 [your usual conditions][actions to perform].

중요 사항 :

  1. 원하는 결과를 인쇄하기 만하면 작업을 수행하지 않아도됩니다 -print. 일반적 으로을 사용할 때는 그렇게하고 싶지 않습니다-prune .

    find의 기본 동작은 끝에 아이러니 한 동작 이외의 동작이없는 경우 동작 과 함께 전체을 "및" -print수행하는 것 -prune입니다. 그것은 이것을 쓰는 것을 의미합니다 :

    find . -name .snapshot -prune -o -name '*.foo'              # DON'T DO THIS
    

    이것을 쓰는 것과 같습니다.

    find . \( -name .snapshot -prune -o -name '*.foo' \) -print # DON'T DO THIS
    

    이것은 정리하고있는 디렉토리의 이름도 인쇄한다는 것을 의미합니다. 일반적으로 원하는 이름이 아닙니다. 대신 -print원하는 작업 을 명시 적으로 지정하는 것이 좋습니다.

    find . -name .snapshot -prune -o -name '*.foo' -print       # DO THIS
    
  2. "정상 조건"이 프룬 조건과 일치하는 파일과 일치하면 해당 파일이 출력에 포함 되지 않습니다 . 이 문제를 해결하는 방법은 -type d프룬 조건에 술어를 추가하는 것 입니다.

    예를 들어, 우리가 시작한 디렉토리를 제거하려고한다고 가정하고 .git(이것은 다소 다소 고안된 것입니다-일반적으로 정확히 이름을 가진 것만 제거하면 됩니다.git ), 이외의 파일을 포함하여 모든 파일을 보려고했습니다 .gitignore. 이것을 시도 할 수 있습니다 :

    find . -name '.git*' -prune -o -type f -print               # DON'T DO THIS
    

    이것은 출력에 포함 되지 않습니다.gitignore . 고정 버전은 다음과 같습니다.

    find . -type d -name '.git*' -prune -o -type f -print       # DO THIS
    

추가 팁 : GNU 버전 find의을 사용하는 경우 texinfo 페이지에 대한 find맨 페이지보다 자세한 설명이 있습니다 (대부분의 GNU 유틸리티에 해당됨).


일부가 말했듯 이 -prune은 어떤 디렉토리 내려가는 것을 막지 않습니다 . 적용된 테스트와 일치하는 디렉토리로 내려 가지 않습니다. 아마도 일부 예제가 도움이 될 것입니다 (정규 예제의 맨 아래 참조). 너무 길어서 죄송합니다.

$ find . -printf "%y %p\n"    # print the file type the first time FYI
d .
f ./test
d ./dir1
d ./dir1/test
f ./dir1/test/file
f ./dir1/test/test
d ./dir1/scripts
f ./dir1/scripts/myscript.pl
f ./dir1/scripts/myscript.sh
f ./dir1/scripts/myscript.py
d ./dir2
d ./dir2/test
f ./dir2/test/file
f ./dir2/test/myscript.pl
f ./dir2/test/myscript.sh

$ find . -name test
./test
./dir1/test
./dir1/test/test
./dir2/test

$ find . -prune
.

$ find . -name test -prune
./test
./dir1/test
./dir2/test

$ find . -name test -prune -o -print
.
./dir1
./dir1/scripts
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.sh
./dir1/scripts/myscript.py
./dir2

$ find . -regex ".*/my.*p.$"
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.py
./dir2/test/myscript.pl

$ find . -name test -prune -regex ".*/my.*p.$"
(no results)

$ find . -name test -prune -o -regex ".*/my.*p.$"
./test
./dir1/test
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.py
./dir2/test

$ find . -regex ".*/my.*p.$" -a -not -regex ".*test.*"
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.py

$ find . -not -regex ".*test.*"                   .
./dir1
./dir1/scripts
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.sh
./dir1/scripts/myscript.py
./dir2

일반적으로 우리가 리눅스에서 일하는 기본 방식과 생각 방식은 왼쪽에서 오른쪽입니다.
따라서 먼저 찾고있는 것을 작성하십시오.

find / -name "*.php"

그런 다음 enter 키를 누르고 원하지 않는 디렉토리에서 너무 많은 파일을 가져오고 있음을 알 수 있습니다. 마운트 된 드라이브를 검색하지 않도록 / media를 제외 시키십시오.
이제 이전 명령에 다음을 추가하면됩니다.

-print -o -path '/media' -prune

최종 명령은 다음과 같습니다.

find / -name "*.php" -print -o -path '/media' -prune

............... | <--- 포함 ---> | .................... | <- -------- 제외 ---------> |

I think this structure is much easier and correlates to the right approach


Adding to the advice given in other answers (I have no rep to create replies)...

When combining -prune with other expressions, there is a subtle difference in behavior depending on which other expressions are used.

@Laurence Gonsalves' example will find the "*.foo" files that aren't under ".snapshot" directories:-

find . -name .snapshot -prune -o -name '*.foo' -print

However, this slightly different short-hand will, perhaps inadvertently, also list the .snapshot directory (and any nested .snapshot directories):-

find . -name .snapshot -prune -o -name '*.foo'

The reason is (according to the manpage on my system):-

If the given expression does not contain any of the primaries -exec, -ls, -ok, or -print, the given expression is effectively replaced by:

( given_expression ) -print

That is, the second example is the equivalent of entering the following, thereby modifying the grouping of terms:-

find . \( -name .snapshot -prune -o -name '*.foo' \) -print

This has at least been seen on Solaris 5.10. Having used various flavors of *nix for approx 10 years, I've only recently searched for a reason why this occurs.


Prune is a do not recurse at any directory switch.

From the man page

If -depth is not given, true; if the file is a directory, do not descend into it. If -depth is given, false; no effect.

Basically it will not desend into any sub directories.

Take this example:

You have the following directories

  • /home/test2
  • /home/test2/test2

If you run find -name test2:

It will return both directories

If you run find -name test2 -prune:

It will return only /home/test2 as it will not descend into /home/test2 to find /home/test2/test2


I am no expert at this (and this page was very helpful along with http://mywiki.wooledge.org/UsingFind)

Just noticed -path is for a path that fully matches the string/path that comes just after find (. in theses examples) where as -name matches all basenames.

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

blocks the .git directory in your current directory ( as your finding in . )

find . -name .git  -prune -o -name file  -print

blocks all .git subdirectories recursively.

Note the ./ is extremely important!! -path must match a path anchored to . or whatever comes just after find if you get matches with out it (from the other side of the or '-o') there probably not being pruned! I was naively unaware of this and it put me of using -path when it is great when you don't want to prune all subdirectory with the same basename :D


Show everything including dir itself but not its long boring contents:

find . -print -name dir -prune

If you read all the good answers here my understanding now is that the following all return the same results:

find . -path ./dir1\*  -prune -o -print

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

find . -path ./dir1\*  -o -print
#look no prune at all!

But the last one will take a lot longer as it still searches out everything in dir1. I guess the real question is how to -or out unwanted results without actually searching them.

So I guess prune means don't decent past matches but mark it as done...

http://www.gnu.org/software/findutils/manual/html_mono/find.html "This however is not due to the effect of the ‘-prune’ action (which only prevents further descent, it doesn't make sure we ignore that item). Instead, this effect is due to the use of ‘-o’. Since the left hand side of the “or” condition has succeeded for ./src/emacs, it is not necessary to evaluate the right-hand-side (‘-print’) at all for this particular file."


find builds a list of files. It applies the predicate you supplied to each one and returns those that pass.

This idea that -prune means exclude from results was really confusing for me. You can exclude a file without prune:

find -name 'bad_guy' -o -name 'good_guy' -print  // good_guy

All -prune does is alter the behavior of the search. If the current match is a directory, it says "hey find, that file you just matched, dont descend into it". It just removes that tree (but not the file itself) from the list of files to search.

It should be named -dont-descend.

참고URL : https://stackoverflow.com/questions/1489277/how-to-use-prune-option-of-find-in-sh

반응형