How to use '-prune' option of 'find' in sh? Ask Question

How to use '-prune' option of 'find' in sh? Ask Question

I don't quite understand the example given from the man find, can anyone give me some examples and explanations? Can I combine regular expression in it?


The more detailed question is like this:

Write a shell script, changeall, which has an interface like changeall [-r|-R] "string1" "string2". It will find all files with an suffix of .h, .C, .cc, or .cpp and change all occurrences of string1 to string2. -r is option for staying in current dir only or including subdir's.

NOTE:

  1. For non-recursive case, ls is NOT allowed, we could only use find and sed.
  2. I tried find -depth but it was NOT supported. That's why I was wondering if -prune could help, but didn't understand the example from man find.

EDIT2: I was doing assignment, I didn't ask question in great details because I would like to finish it myself. Since I already done it and hand it in, now I can state the whole question. Also, I managed to finish the assignment without using -prune, but would like to learn it anyway.

ベストアンサー1

The thing I'd found confusing about -prune is that it's an action (like -print), not a test (like -name). It alters the "to-do" list, but always returns true.

The general pattern for using -prune is this:

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

You pretty much always want the -o (logical OR) immediately after -prune, because that first part of the test (up to and including -prune) will return false for the stuff you actually want (ie: the stuff you don't want to prune out).

Here's an example:

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

This will find the "*.foo" files that aren't under ".snapshot" directories. In this example, -name .snapshot makes up the [conditions to prune], and -name '*.foo' -print is [your usual conditions] and [actions to perform].

Important notes:

  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その man ページよりも詳細な説明があります (ほとんどの GNU ユーティリティに当てはまります)。

おすすめ記事