TL; DR:の-exec rm代わりに使用するのが最善の方法です-delete。
find a \( -name b -prune \) -o -type f -exec rm {} +
説明:
で使用しようとする-deleteと、なぜfindが文句を言うの-pruneですか?
短い答え:-delete暗示-depthし-depthて-prune無効にするため。
長い回答をする前に、まずfindの有無によるfindの動作を観察します-depth。
$ find foo/
foo/
foo/f1
foo/bar
foo/bar/b2
foo/bar/b1
foo/f2
1つのディレクトリでの順序については保証されません。ただし、ディレクトリはその内容の前に処理されることが保証されています。foo/何よりも前に、foo/*そしてfoo/bar何よりも前に注意してくださいfoo/bar/*。
これはで元に戻すことができます-depth。
$ find foo/ -depth
foo/f2
foo/bar/b2
foo/bar/b1
foo/bar
foo/f1
foo/
すべてfoo/*が以前に表示されることに注意してくださいfoo/。と同じfoo/barです。
より長い答え:
-prunefindがディレクトリに降りないようにします。つまり-prune、ディレクトリの内容をスキップします。あなたの場合-name b -prune、findがという名前のディレクトリに下降するのを防ぎますb。
-depthディレクトリ自体の前にディレクトリの内容を処理することを見つけます。つまり、findがディレクトリエントリを処理できるようになるまでに、bその内容はすでに処理されています。したがって、効果-pruneはありませ-depthん。
-delete-depth最初にファイルを削除してから空のディレクトリを削除できることを意味します。-delete空でないディレクトリの削除を拒否します。-delete空ではないディレクトリを強制的に削除するオプションや-delete、暗黙的に防止するオプションを追加することは可能だと思います-depth。しかし、それは別の話です。
あなたが望むものを達成する別の方法があります:
find a -not -path "*/b*" -type f -delete
これは覚えやすいかもしれません。
このコマンドはまだディレクトリに降りて、それらを拒否するbためだけに-notその中のすべてのファイルを処理します。ディレクトリbが巨大な場合、これはパフォーマンスの問題になる可能性があります。
-pathとは動作が異なり-nameます。はパス全体と一致し-nameますが、(ファイルまたはディレクトリの)名前-pathとのみ一致します。たとえば、パスを観察します/home/lesmana/foo/bar。-name -bar名前がであるため一致しbarます。-path "*/foo*"文字列/fooがパスに含まれているため一致します。-path使用する前に理解しておくべき複雑な点があります。find詳細については、のマニュアルページを参照してください。
これは100%万能ではないことに注意してください。「誤検知」の可能性があります。上記のコマンドの記述方法では、名前がb(ポジティブ)で始まる親ディレクトリを持つファイルはスキップされます。ただしb、ツリー内の位置に関係なく、名前が先頭にあるファイルもすべてスキップします(誤検知)。これは、より優れた式を書くことで修正できます"*/b*"。それは読者のための練習問題として残されています。
私はあなたがプレースホルダーとして使用aしb、本名がallosaurusandに似ていると思いbrachiosaurusます。brachiosaurus代わりに置くとb、誤検知の量が大幅に減少します。
少なくとも誤検知は削除されないので、それほど悲劇的ではありません。さらに、最初にコマンドを実行せずに-delete(ただし、暗黙のを配置することを忘れないで)、誤出力をチェックし-depth、出力を調べることができます。
find a -not -path "*/b*" -type f -depth
a除いてはa/b?