web-dev-qa-db-ja.com

shで 'find'の '-Prune'オプションを使用する方法は?

私はman findから与えられた例をよく理解していません、誰かが私にいくつかの例と説明を与えてくれますか正規表現を組み合わせることができますか?


より詳細な質問は次のとおりです。

changeall [-r|-R] "string1" "string2"のようなインターフェイスを持つシェルスクリプトchangeallを作成します。接尾辞が.h.C.cc、または.cppのすべてのファイルを検索し、string1のすべての出現箇所をstring2に変更します。 -rは、現在のディレクトリのみに滞在するか、サブディレクトリを含めるためのオプションです。

注意:

  1. 非再帰的な場合、lsは許可されません。findsedのみを使用できます。
  2. find -depthを試しましたが、サポートされていませんでした。そのため、-Pruneが役立つかどうか疑問に思っていましたが、man findの例を理解していませんでした。

EDIT2:私は割り当てを行っていました、私はそれを自分で終えたいので、私は非常に詳細に質問をしませんでした。私はすでにそれを行って提出しているので、今では質問全体を述べることができます。また、-Pruneを使用せずに割り当てを完了することができましたが、とにかく学習したいと思います。

204
derrdji

-Pruneについて混乱しているのは、テスト(-printなど)ではなく、アクション(-nameなど)であることです。 「to-do」リストを変更しますただし、常にtrueを返します

-Pruneを使用する一般的なパターンは次のとおりです。

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

テストの最初の部分(-oを含む)は、実際に必要なもの(つまり:もの)に対してfalseを返すため、-Pruneの直後に-Prune(論理OR)が必要になります。 you do n'tプルーニングしたい)。

以下に例を示します。

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アクションを省くのに慣れているかもしれません。あなたは通常do n't-Pruneを使用するときにそれをしたいです。

    Findのデフォルトの動作は、末尾に-print以外のアクションがない場合(皮肉なことに)-Pruneアクションでentire式を「and」することです。これは、これを書くことを意味します:

    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. 「通常の状態」がプルーンの状態にも一致するファイルと一致する場合、それらのファイルはnotに出力に含まれます。これを修正する方法は、プルーン条件に-type d述部を追加することです。

    たとえば、.gitで始まるディレクトリを削除したいとします(これは明らかにやや不自然です-通常はexactly.gitという名前のもののみを削除する必要があります) .gitignoreなどのファイルを含むすべてのファイル。あなたはこれを試すかもしれません:

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

    これは、出力に.gitignoreを含めるnotになります。修正版は次のとおりです。

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

追加のヒント:GNUバージョンのfindを使用している場合、findのtexinfoページには、そのマンページよりも詳細な説明があります(ほとんどのGNUユーティリティ)。

410

-Pruneはanyディレクトリへの下降を妨げるものではないことに注意してください。これは、適用されるテストに一致するディレクトリへの下降を防ぎます。おそらくいくつかの例が役立つでしょう(正規表現の例については下を参照)。これはとても長くてすみません。

$ 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
26

通常、Linuxで物事を行うネイティブな方法と私たちが考える方法は左から右です。
だから、まずあなたが探しているものを書きます:

find / -name "*.php"

その後、おそらくエンターキーを押し、あなたがしたくないディレクトリからあまりにも多くのファイルを取得していることに気付きます。マウントされたドライブを検索しないように/ mediaを除外しましょう。
次のコマンドを前のコマンドに追加するだけです。

-print -o -path '/media' -Prune

最終的なコマンドは次のとおりです。

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

............... | <---含める---> | .................... | <- --------除外---------> |

この構造ははるかに簡単で、正しいアプローチと相関していると思います

24
AmitP

他の回答で与えられたアドバイスに追加する(返信を作成する担当者がいない)...

-Pruneを他の式と組み合わせる場合、使用される他の式によって動作に微妙な違いがあります。

@Laurence Gonsalvesの例は、「。snapshot」ディレクトリの下にない「* .foo」ファイルを検索します。

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

ただし、このわずかに異なる短縮形は、おそらく誤って.snapshotディレクトリ(およびネストされた.snapshotディレクトリ)もリストします。

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

その理由は(私のシステムのマンページによると):-

指定された式にプライマリ-exec、-ls、-ok、または-printのいずれも含まれていない場合、指定された式は次のように効果的に置き換えられます。

(given_expression)-print

つまり、2番目の例は次を入力することと同等であり、それによって用語のグループ化を変更します。

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

これは少なくともSolaris 5.10で見られます。さまざまなフレーバーの* nixを約10年間使用してきたので、最近これが発生する理由を検索しました。

9
crw

プルーンは、どのディレクトリスイッチでも再帰しま​​せん。

マニュアルページから

-depthが指定されていない場合、true。ファイルがディレクトリである場合は、そのディレクトリに降りないでください。 -depthが指定されている場合はfalse。無効。

基本的に、サブディレクトリには送信されません。

この例を見てください:

次のディレクトリがあります

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

find -name test2を実行する場合:

両方のディレクトリを返します

find -name test2 -Pruneを実行する場合:

/ home/test2/test2を見つけるために/ home/test2に下がらないため、/ home/test2のみを返します。

3
AdamW

Dir自体を含むすべてを表示しますが、長く退屈な内容は表示しません。

find . -print -name dir -Prune
1
devon

ここですべての良い答えを読んだ場合、私の理解は、次はすべて同じ結果を返すということです。

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

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

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

Butdir1内のすべてを検索するため、最後のものはもっと長くかかります。本当の問題は、実際に検索せずに、不要な結果を-orアウトする方法だと思います。

だから、プルーンは過去の試合をまともではなく、完了としてマークすることを意味すると思います...

http://www.gnu.org/software/findutils/manual/html_mono/find.html 「ただし、これは「-プルーン」アクションの影響によるものではありません、そのアイテムを無視することを確認しません)代わりに、この効果は「-o」の使用によるものです。「/」条件の左側は./src/emacsで成功しているため、この特定のファイルの右側(「印刷」)を評価する必要はまったくありません。」

0
sabgenton

findは、ファイルのリストを作成します。指定した述語をそれぞれに適用し、合格したものを返します。

-Pruneが結果から除外することを意味するというこの考えは、私にとって本当に混乱しました。 Pruneなしでファイルを除外できます。

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

-Pruneは、検索の動作を変更するだけです。現在の一致がディレクトリである場合、"ちょっとfind、あなたがちょうど一致したそのファイル、そこに降りてはいけない"と言います。検索するファイルのリストからそのツリー(ファイル自体ではない)を削除するだけです。

-dont-descendという名前にする必要があります。

0
seeker_of_bacon