253

の例がよくわかりませんman find。誰か例と説明を教えてもらえますか? 正規表現を組み合わせることはできますか?


より詳細な質問は次のようになります。

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

ノート:

  1. 非再帰の場合、lsは許​​可されません。使用できるのはfindandだけsedです。
  2. 試してみfind -depthましたが、サポートされていませんでした。-pruneそのため、役立つかどうか疑問に思っていましたが、 の例がわかりませんでしたman find

EDIT2:私は課題をしていました。自分で終わらせたいので、詳細な質問はしませんでした。私はすでにそれを行って提出したので、今、私は質問全体を述べることができます. また、 を使わずになんとか課題を終わらせました-pruneが、とにかく学びたいと思います。

4

10 に答える 10

507

私が混乱して-pruneいたのは、それがアクション ( など-print) であり、テスト ( など) ではないということ-nameです。「to-do」リストを変更しますが、常に 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 のデフォルトの動作は、 (皮肉なことに) 末尾以外にアクションがない場合、式全体にアクションを「AND」することです。つまり、次のように記述します。-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 . -name '.git*' -type d -prune -o -type f -print       # DO THIS
    

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

于 2009-09-28T21:12:49.720 に答える
28

一部の人が言っているように、 -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
于 2009-09-29T00:04:53.583 に答える
15

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

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

@Laurence Gonsalves の例では、「.snapshot」ディレクトリの下にない「*.foo」ファイルが検出されます。

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

ただし、このわずかに異なる省略形は、おそらく不注意で、.snapshotディレクトリ (およびネストされた .snapshot ディレクトリ)もリストします。

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

posix manpageによると、理由は次のとおりです。

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

(与えられた式) -print

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

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

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

于 2012-07-04T10:23:51.637 に答える
2

Pruneは、「このファイルで再帰しない」スイッチ(アクション)です。

マニュアルページから

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

基本的に、サブディレクトリには移動しません。

この例を見てください:

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

% find home
home
home/test1
home/test1/test1
home/test2
home/test2/test2

find home -name test2test2という名前の親ディレクトリと子ディレクトリの両方を出力します。

% find home -name test2
home/test2
home/test2/test2

さて、-pruneで..。

find home -name test2 -prune/ home/test2のみを出力します; / home / test2 / test2に降りて/home/ test2/test2を見つけることはありません。

% find home -name test2 -prune
home/test2
于 2009-09-28T20:51:59.420 に答える
2

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

find . -print -name dir -prune
于 2014-10-24T18:52:22.990 に答える
1

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

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

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

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

ただし、最後の 1 つは、まだ dir1 内のすべてを検索するため、はるかに時間がかかります。-or本当の問題は、実際に検索せずに不要な結果を削除する方法だと思います。

したがって、プルーンとは、過去の試合を適切に処理するのではなく、完了としてマークすることを意味すると思います...

http://www.gnu.org/software/findutils/manual/html_mono/find.html 「ただし、これは '-prune' アクションの影響によるものではありません (これは、それ以上の降下を防ぐだけで、その項目を無視します). 代わりに, この効果は '-o' の使用によるものです. ./src/emacs では「or」条件の左側が成功したため、右側の -この特定のファイルについては、手元 ('-print') をまったく使用しません。"

于 2014-09-19T03:43:29.070 に答える