`find`の出力に基づいてディレクトリを削除する方法は?


148

次のコマンドを発行して、.svnディレクトリを見つけます。

find . -name ".svn"

次の結果が得られます。

./toto/.svn
./toto/titi/.svn
./toto/tata/.svn

rm -frディレクトリとそのコンテンツを削除するために、これらすべての行をどのように処理できますか?


3
GNU findには-deleteオプションがあります。
マルコ

5
または-exec rm -r "{}" \;、検索の最後に追加することができます-使用する場合は注意してrm -rください!:)
Drav Sloan

10
@Marco削除オプションはディレクトリでは機能しないようです。
アルノー

@SuperChafouinここでは、ファイルとディレクトリで完全に機能します。ポイントは、emtpyディレクトリのみを削除し、指定する-name ".svn".svnディレクトリ自体にのみ一致し、ディレクトリにあるファイルには一致しないことです.svn
マルコ

1
@SuperChafouin。ただし、スペースが含まれるパスでは機能しません(したがって-execquotedで使用"{}")。
Dravスローン

回答:


194

Findは-exec、見つかった一致ごとにオプションを指定して引数を実行できます。スペース/改行およびその他の文字が含まれるパスを正しく処理できるため、推奨されるメカニズムです。ディレクトリ自体を削除する前に、ディレクトリの内容を削除する必要があるため-rrmコマンドで使用してこれを実現します。

あなたの例では、次を発行できます:

find . -name ".svn" -exec rm -r "{}" \;

また、チェックを追加することで、.svnという名前のディレクトリを検索するようにfindに指示することもできます-type d

find . -name ".svn" -type d -exec rm -r "{}" \;

警告rm -rフォルダとそのすべてのコンテンツを削除する場合は注意して使用してください。

空のディレクトリだけでなく、空のディレクトリのみを含むディレクトリを削除する場合は、findで-deleteand を使用して削除できます-empty

find . -name ".svn" -type d -empty -delete

22
私は常に実行するためのアドバイスを見てきた-type -nameに呼び出しているため、検索コマンドでのstat型を取得するためには高価です。かなり多くのファイルを試してみましたが、find . -name 'foo' -type d実は19秒find . -type d -name 'foo'かかったのに32秒かかったようです。したがって、-type最初に実行する時間は約50%長くなります。
スピンアップ15年

6
私はこのコマンドを何年も使用していますが、Macではこれらのディレクトリが存在しないというエラーが表示されます。それらは削除されますが。メッセージを見たことがありません。
チョビー

1
@chovyと同じです。これらのメッセージを取り除く方法はありますか?
クレメント

2
@chovy @clémentそれはfind、フォルダーを同時に削除する一方で、そのフォルダー内の他の一致を確認したいためです。〜まだこれを修正する方法がわかりません。〜ダーティー修正:find . -name "folder-to-delete" -print0 | xargs -r0 -- rm -r
チャーリー

5
@chovy @Clément私は-depth引数がこれを修正すると思う:find . -depth -name ".svn" -type d -exec rm -r "{}" \;
-gimboland

67

ここに受け入れられた答えの方法よりもまだ速いポータブルです。

コマンドターミネータ+としてセミコロンの代わりにを使用するとfind、CPU使用率が最適化されます。.svnサブディレクトリがたくさんある場合、それは重要です。

find . -name .svn -type d -exec rm -rf {} +

あなたは決してことにも注意1つの必要性ここに中括弧を引用します。

1fishシェルを使用しない限り。


5
+とセミコロンの違いは何ですか?中括弧を使用しないのはなぜですか?
石城郭

1
@ShichengGuoセミコロンを使用すると、見つかったディレクトリごとに1つのrmコマンドがあり、+を使用すると、見つかったすべてのディレクトリ(または少なくとも非常に多数のディレクトリ)が処理されます。ここでは中括弧が使用されます。
jlliagre

@ShichengGuoは、ここで中括弧を引用する必要がない理由を意味していると思います(@jlliagreは、それらを引用する必要はないと書いています)。現在、参照を見つけることができませんが、{}に置き換えられたパスをfindが自動的にエスケープするためです。
クインコメンダント

+が何をするかについての答えと質問はまったく正しくありません。多くのファイルが見つかった場合、「;」「コマンドラインが長すぎます」エラーが発生します。+は、コマンドラインの最大長より短いバッチで見つかったファイルを分割し、各バッチに対してコマンドを実行します。
gaoithe

1
@gaoithe私はあなたが編集したロールバックを行い、正しい文を間違った文に置き換えました。を使用するとCPU使用率+ 低下しますが、使用; てもコマンドが長すぎるエラーになりません
jlliagre

27

gnu findを使用していると仮定すると、-deleteオプションを使用できます:

find . -name test -delete

覚えやすいです。


コマンドの説明(またはソリューションをバックアップするためのドキュメント)で投稿を拡大することを検討してください。多くの場合、1行(または2行)の回答が最も印象的ではありません。
HalosGhost 14

94
これは、空でないディレクトリでは機能しません。
ベラク14

2
Mac OS Xでも動作します
描画

これは、非空のフォルダでは動作しませんが、それはより簡単&安全なソリューションです
RousseauAlexandre

オプションの順序は非常に重要ですので、-deleteは最後の1でなければならないために、それらを実行します見つける
ホセ・イグナシオCenteno

13

私が使用するときのコンピューター上:

find . \( -name dirname -type d \) -exec rm -r '{}' ';'

ディレクトリは削除されますが、エラーが表示されます。

find: ‘./dirname’: No such file or directory

各ディレクトリに対して。

ディレクトリは空ではないため、-deleteオプションは機能しません。私はこの行動の理由をここで見つけました:

  1. findは(必ずしもではありませんが)./ディレクトリの最初のエントリを取得します。これは、たとえばdir.1 /になります
  2. それをパターン「dir。?」と比較します。一致しますか?はい。
  3. findは「rm -r dir.1」を実行します。
  4. findは、dir.1 /を入力して、ディレクトリ内のパターンを見つけようとします。execコマンドについては何も知りません。
  5. dir.1 /はもう見つかりません。ENOENTを返します(strace出力を見てください)

代わりにこれを使用して回避します:

rm -r `find . -name dirname -type d`

findはdirnameという名前のディレクトリへの再帰を試みますが、これは実際には必要ではなく、さらに時間がかかります。ディレクトリ構造によっては、--depthfindオプションを使用してこの問題を回避できる場合があります。さらに、dirname / foo / dirnameのようなディレクトリ構造がある場合、rmから「No such file or directory」エラーが発生します。エラーを抑制するには、stderrを/ dev / nullにリダイレクトするか-f、rmで(force)フラグを使用します。


2
悪いアイデアは:スペースを含むファイル名は恐ろしい問題のすべての種類の原因となります
クレマン

2
将来の読者向け:find . -name "to-delete" -print0 | xargs -r0 -- rm -rスペースでクラッシュしないフェイルプルーフバージョン
チャーリー

3
追加する必要があるunix.stackexchange.com/a/115869/8257を参照してください-prune
マピオ

1
-prune「そのようなファイルまたはディレクトリがありません」エラーを回避するために追加します。
ジュリアンカルシケ

12

これを行うより速い方法は次のとおりです。

find . -name ".svn" -type d -prune -exec rm -rf '{}' '+'

別の「.svn」の中に「.svn」がある場合。


サブディレクトリで削除するディレクトリを見つけたい場合、これはあまり役に立ちません。
アレクシスウィルケ

5

Bash固有のソリューション:

shopt -s globstar
rm -r **/.svn
shopt -u globstar #optional. this will disable globstar expansion

3
多くのファイルに一致するグロブのコマンドライン拡張については、このメカニズムと一致できるファイルの数に制限があります。この制限を超えるとbash: /bin/rm: Argument list too long
Drav Sloan

1
@DravSloanは正しいですが、その制限は数十万のファイルにあります。心に留めておくべきことですが、おそらくほとんどの人にとっては問題にはなりません。
evilsoup

4

この-deleteアクションは-pathテストでうまく機能することがわかりました。たとえば、次の問題は元のポスターの問題で機能するはずです。

find . -path '*/.svn*' -delete

本気ですか?-deleteはを意味-depthし、システム上の空でないディレクトリを確実に削除します。
マグナス

再テストされ、動作します。たぶんそれは私が修正した単なるタイプミスでした。
ケノーブ

私もこのアプローチを試みましたが、うまくいきました-ディレクトリは削除されました。
アラン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.