我发出以下命令来查找.svn目录:

find . -name ".svn"


这给了我以下结果:

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


如何使用rm -fr处理所有这些行以删除目录及其内容?

评论

GNU find具有-delete选项。

或者,您可以添加-exec rm -r“ {}” \;到发现的最后-使用rm -r时要小心! :)

@Marco Delete选项似乎不适用于目录。

@SuperChafouin在文件和目录上,它工作得很好。关键是它仅删除emtpy目录,并且当您指定-name“ .svn”时,它仅与.svn目录本身匹配,而不与.svn目录中的文件匹配。

@SuperChafouin,但不适用于其中带有空格的路径(因此使用带-exec并带有引号“ {}”的路径)。

#1 楼

Find可以为找到的每个匹配项使用-exec选项执行参数。这是推荐的机制,因为您可以正确处理带有空格/换行符和其他字符的路径。您必须先删除目录的内容,然后才能删除目录本身,因此请使用带有-r命令的rm来实现此目的。

对于您的示例,您可以发出:

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


您还可以通过添加-type d检查来告诉find只是找到名为.svn的目录:

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


警告将rm -r与警告,它会删除该文件夹及其所有内容。

如果要删除仅空目录以及仅包含空目录的目录,请使用-delete-empty自己进行删除:

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


评论


我已经看到了在find命令中始终在-name之后运行-type的建议,因为调用stat来获取类型很昂贵。我只是自己在相当大的文件上尝试过,这似乎是对的:运行find。 -name'foo'-type d花了19秒,而find。 -type d -name'foo'用了32秒。因此,先运行-type的时间延长约50%。

–旋转
2015年3月16日16:37



我已经使用此命令多年,但是现在在Mac上,我收到错误消息,指出这些目录不存在。即使确实删除了它们。我以前从没看过消息。

–碎肉
15/12/23在8:51

与@chovy相同。有办法摆脱这些消息吗?

–Clément
16年4月23日在15:32

@chovy @clément这是因为find希望在该文件夹中查看其他匹配项,同时它正在删除该文件夹。 〜我还不知道该如何解决。〜肮脏的解决方法:查找。名称“删除文件夹” -print0 | xargs -r0-rm -r

–查理
16 Jul 20'12:02



@chovy @Clément我认为-depth参数可以解决此问题:find。 -depth -name“ .svn” -type d -exec rm -r“ {}” \;

–金博兰
16 Jul 27'7:57



#2 楼

这是一种比接受的答案方式还快的便携式方法。

使用+代替分号,因为find命令终止符可以优化CPU使用率。如果您有很多.svn子目录,那么这可能很重要:

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


请注意,您永远不需要在这里引用花括号。

1除非您使用fish shell(自从我写完此回复以来,这个问题可能已经解决了)。

评论


+和分号有什么区别?为什么我们不使用花括号?

–郭世成
17年1月4日在19:25

@ShichengGuo使用分号,将在每个目录中找到一个rm命令,使用+单个rm命令将处理找到的所有目录(或至少其中很大的一个)。我没有第二个问题,卷曲在这里使用大括号。

– jlliagre
17年1月4日在20:13

我认为@ShichengGuo意味着我们为什么不需要在这里引用花括号(@jlliagre写道,我们永远不需要引用它们)。我现在找不到参考,但是我知道这是因为find会自动转义替换为{}的路径。

– Quinn Comendant
17 Mar 8 '17 at 6:47



答案和问题对+的作用不太正确。如果找到许多文件,则为“;”将给出“命令行太长”错误。 +分割小于最大允许命令行长度的批处理中找到的文件,并为每个批处理运行命令。

–gaoithe
17 Mar 22 '17 at 11:56

@gaoithe我确实回滚了您编辑的内容,其中用不正确的语句替换了正确的语句。使用+确实可以减少CPU使用率,使用;可以;不会导致命令太长的错误。

– jlliagre
17 Mar 22 '17 at 12:26



#3 楼

假设您使用的是gnu find,则可以使用-delete选项:

find . -name test -delete


,它更容易记住。

评论


考虑扩展您的帖子,并附上命令的说明(或文档以备份您的解决方案)。通常一(或两个)行答案不是最有启发性的。

– HalosGhost
2014年8月10日23:02

这不适用于非空目录。

– Belacqua
2014年12月16日20:47

在Mac OS X上也可以使用

–画
16-3-29在3:11

这不适用于非空文件夹,但这是更简单,更安全的解决方案

–卢梭·亚历山大(RousseauAlexandre)
18年2月7日在16:01

选项顺序非常重要,查找将按顺序执行它们,因此-delete必须是最后一个

–乔斯·伊格纳西奥·森特诺(Jose Ignacio Centeno)
18 Mar 6 '18 at 7:25

#4 楼

当我使用计算机时:

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


目录已删除,但出现错误:

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


对于每个目录。

我的目录不是空的,因此-delete选项对我不起作用。我在这里找到了这种现象的原因:



查找(不一定)在./目录中的第一个条目。这将是例如dir.1 /
将其与模式“ dir。?”进行比较。匹配吗?是。
find执行“ rm -r dir.1”。
find尝试输入dir.1 /以在目录中查找模式。它对exec命令一无所知。
它再也找不到dir.1 /。返回ENOENT(查看strace输出)



我改用此方法来解决:

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


请记住,find仍将尝试递归到名为dirname的目录中,这实际上不是必需的,并且会花费一些时间。根据您的目录结构,您也许可以使用--depth查找选项解决此问题。另外,如果您具有目录名/目录名/ foo /目录名之类的目录结构,则会从rm中收到“无此文件或目录”错误。要消除错误,您可以将stderr重定向到/ dev / null或将rm用作-f(force)标志。

评论


坏主意:带空格的文件名会引起各种可怕的问题

–Clément
16年4月23日在15:31

对于将来的读者:查找。名称“要删除” -print0 | xargs -r0-rm -r是一个防故障版本,不会在空间上崩溃

–查理
16年7月20日在12:08

请参阅unix.stackexchange.com/a/115869/8257,您需要添加-prune。

– Mapio
17年1月29日在1:59

添加-prune以避免出现“无此类文件或目录”错误。

–朱利安·卡塞克(Julien Carsique)
17年2月24日在16:25

#5 楼

更快的方法是:

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


如果在另一个“ .svn”中包含“ .svn”。

评论


如果您要查找要删除的目录以及子目录,那不是很有用。

– Alexis Wilke
18年8月1日在7:47

使用-prune是最准确的方法。谢谢!

–alexandre1985
20年6月27日在15:10

#6 楼

重击特定解决方案:

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


评论


请注意,对于与许多文件匹配的glob的命令行扩展,使用此机制可以匹配的文件数是有限制的。超过此限制将导致bash:/ bin / rm:参数列表过长

– Drav Sloan
2013年9月9日上午10:06

@DravSloan是正确的,但是该限制在数十万个文件中。这是要牢记的,但对于大多数人来说可能不是问题。

– evilsoup
2013年9月9日上午10:26

#7 楼

我发现-delete动作与-path测试配合得很好。例如,以下操作应该可以解决原始发布者问题:
find . -path '*/.svn*' -delete

请注意,除了删除'.svn'目录(及其内容)之外,这还将删除其名称的所有文件或目录以“ .svn”开头。例如,如果您使用-path '*/.git*',则除了“ .git /”外,还将删除“ .gitignore”和“ .gitattribute”。为避免这种情况,只需删除具有相同名称的目录,请使用:
find . -path '*/.svn/*' -or -name '.svn' -delete

注意.svn后的斜杠。这将首先查找并删除“ .svn”下的所有文件,然后删除.svn目录本身。

评论


你确定吗? -delete表示-depth,它肯定会删除系统上的非空目录。

–马格努斯
17/12/20在13:56

重新测试,它可以工作。也许这只是我改正的错字。

– Kenorb
18年1月5日在22:23

我也尝试了这种方法,并且有效-目录已删除。

–艾伦
18年4月6日在8:38

#8 楼

TLDR
 find . -depth -name .svn -execdir rm -rf {} +
 

详细信息
使用-execdir而不是-exec

来自man find

使用-exec操作存在不可避免的安全问题;您应该改为使用-execdir选项。

在大多数情况下,-execdir可以替代-exec
请使用+,而不要使用;

来自man find

与-exec操作一样,-execdir的'+'形式将建立一个命令行来处理多个匹配文件,但是任何给定的命令调用都只会列出存在于该文件中的文件。相同的子目录。

查找完全匹配的名称时,+;将执行相同的操作,因为在同一目录中不能有两个具有相同名称的文件,但是+将在以下情况下提高性能多个文件/目录在同一目录中匹配您的find表达式。
;也需要从shell中转义,+不需要转义。
使用-depth

man find中:

-depth:在目录本身之前处理每个目录的内容。

避免在删除目录后搜索目录。请参阅:
 $ mkdir -p test/foo/bar
$ find test -name foo -execdir rm -rf {} +
find: ‘test/foo/bar’: No such file or directory
 

对:
 $ mkdir -p test/foo/bar
$ find test -depth -name foo -execdir rm -rf {} +
# no error