フォルダa
でしばらくアクセスされなかったすべてのファイルを再帰的に削除したい 、サブフォルダー b
内のすべてのファイルを除く 。
find a ( -name b -prune ) -o -type f -delete
ただし、エラーメッセージが表示されます:
find:-deleteアクションは自動的に-depthをオンにしますが、-depthが有効な場合は-pruneは
何もしません。とにかく続行したい場合は、
明示的に-depthオプションを使用してください。
-depth
を追加する b
内のすべてのファイルが発生します 含まれるべきであり、してはならない 起こります。
これを機能させるための安全な方法を知っている人はいますか?
承認された回答:
1つの方法は、 -exec rm
を使用することです。 -delete
の代わりに 。
find a ( -name b -prune ) -o -type f -exec rm {} +
または、 -not -path
を使用します -prune
の代わりに :
find a -not -path "*/b*" -type f -delete
-prune
の理由の説明 -delete
と衝突します :
-delete
を使おうとすると文句を見つけます -prune
を使用 -delete
-depth
を意味します および-depth
-prune
を作成します 効果がありません。
-depth
がある場合とない場合の検索の動作を観察します :
$ find foo/
foo/
foo/f1
foo/bar
foo/bar/b2
foo/bar/b1
foo/f2
単一のディレクトリでの順序についての保証はありません。ただし、ディレクトリがその内容の前に処理されるという保証があります。 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
と同じ 。
詳細説明:
-整理
検索がディレクトリに降りるのを防ぎます。言い換えれば、-prune
ディレクトリの内容をスキップします。あなたの場合、-name b -prune
これは、findがb
という名前のディレクトリに到達したときを意味します すべてのサブディレクトリを含むディレクトリをスキップします。-深さコード> ディレクトリ自体の前にディレクトリの内容を処理するためにfindを作成します。つまり、findがディレクトリエントリ
b
を処理するまでに その内容はすでに処理されています。したがって、-prune
-depth
では効果がありません 事実上。-削除
-depth
を意味します そのため、最初にコンテンツを削除してから、空のディレクトリを削除できます。-削除
空でないディレクトリの削除を拒否します。
代替方法の説明:
find a -not -path "*/b*" -type f -delete
これは覚えやすい場合とそうでない場合があります。
このコマンドは引き続きディレクトリb
に移動します そして、のためだけにその中のすべてのファイルを処理します-
ではありません それらを拒否します。ディレクトリb
の場合、これはパフォーマンスの問題になる可能性があります 巨大です。
-path
-name
とは動作が異なります 。 -名前コード>
-path
の間は、(ファイルまたはディレクトリの)名前とのみ一致します パス全体と一致しています。たとえば、パス / home / lesmana / foo / bar
を確認します。 。 -ネームバー
名前がbar
であるため、一致します 。 -path "* / foo *"
文字列/foo
であるため、一致します パスにあります。 -path
使用する前に理解しておくべき複雑な点がいくつかあります。 find
のマニュアルページを読む 詳細については。
これは100%絶対確実ではないことに注意してください。 「誤検知」の可能性があります。上記のコマンドの記述方法では、名前が b
で始まる親ディレクトリを持つファイルはスキップされます。 (ポジティブ)。ただし、名前が b
で始まるファイルもスキップされます。 ツリー内の位置に関係なく(誤検知)。これは、 "* / b *"
よりも優れた式を記述することで修正できます。 。それは読者の練習問題として残されています。
a
を使用したと思います およびb
プレースホルダーと本名はallosaurus
に似ているため およびブラキオサウルス
。 ブラキオサウルス
を入れた場合 b
の代わりに そうすれば、誤検知の量が大幅に減少します。
少なくとも誤検知はではありません 削除されたので、それほど悲劇的ではありません。さらに、最初に -delete
を指定せずにコマンドを実行することで、誤検知をチェックできます。 (ただし、暗黙の -depth
を配置することを忘れないでください )そして出力を調べます。
find a -not -path "*/b*" -type f -depth