a
サブフォルダ内のすべてのファイルを除いて、特定の期間にフォルダにアクセスしなかったすべてのファイルを繰り返し削除したいと思いますb
。
find a \( -name b -prune \) -o -type f -delete
ただし、エラーメッセージが表示されます。
find:-delete操作は自動的に-deepを有効にしますが、-pruneは-deepが適用されている間は何もしません。続行するには、-lengthオプションを明示的に使用してください。
-depth
追加すると、すべてのファイルが含まれます。b
いいえ発生する。
これを行う安全な方法を知っている人はいますか?
ベストアンサー1
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
。
ヒントを与えて作成することはうまくいかないので、withを使用しようとすると-delete
苦情がわかります。-prune
-delete
-depth
-depth
-prune
以下を使用または使用せずに find 動作を観察します-depth
。
$ find foo/
foo/
foo/f1
foo/bar
foo/bar/b2
foo/bar/b1
foo/f2
単一のディレクトリ内の順序は保証されません。ただし、ディレクトリはコンテンツの前に処理されます。foo/
beforefoo/*
とfoo/bar
beforeを参照してくださいfoo/bar/*
。
これは元に戻すことができます-depth
。
$ find foo/ -depth
foo/f2
foo/bar/b2
foo/bar/b1
foo/bar
foo/f1
foo/
現在がfoo/*
beforeの前に来ていることに注意してくださいfoo/
。と同じですfoo/bar
。
さらなる説明:
-prune
find がディレクトリに降りるのを防ぎます。つまり、-prune
ディレクトリの内容をスキップします。あなたの場合、-name b -prune
これは、 find がその名前のディレクトリに到達すると、すべてのb
サブディレクトリを含むそのディレクトリをスキップすることを意味します。-depth
findにディレクトリ自体の前にディレクトリの内容を処理させます。これは、findがディレクトリエントリの処理を開始したときにb
その内容がすでに処理されていることを意味します。したがって、-prune
無効で-depth
有効です。-delete
つまり、-depth
コンテンツを最初に削除してから空のディレクトリを削除できます。-delete
空でないディレクトリの削除を拒否します。
代替方法の説明:
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
andをb
プレースホルダとして使用しており、実際の名前はallosaurus
andに近いと仮定しますbrachiosaurus
。これを置き換えると、誤brachiosaurus
検出b
の数が大幅に減少します。
少なくとも偽の肯定は次のとおりです。いいえあまりにも悲惨でないように削除しました。また、最初にコマンドなしでコマンドを実行し-delete
(暗黙的なコマンドを入力する必要があります-depth
)、出力を調べて誤検出を確認することもできます。
find a -not -path "*/b*" -type f -depth