如何根据`find`输出删除目录?


148

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

find . -name ".svn"

这给了我以下结果:

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

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


3
GNU find具有-delete选项。
Marco Marco

5
或者您可以添加-exec rm -r "{}" \;到查找的末尾-使用时要小心rm -r!:)
Drav Sloan 2013年

10
@Marco Delete选项似乎不适用于目录。
Arnaud 2013年

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

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

Answers:


194

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

例如,您可以发出:

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

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

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

警告rm -r谨慎使用会删除该文件夹及其所有内容。

如果您只想删除空目录以及仅包含空目录的目录,find可以使用-deleteand 本身进行删除-empty

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

21
我见过的建议始终运行-type 后, -name在查找命令,因为呼吁stat要获得类型是昂贵的。我只是自己在相当大的文件上尝试过,这似乎是对的:运行find . -name 'foo' -type d花了19秒,而find . -type d -name 'foo'花了32秒。因此,大约-type要先运行50%以上的时间。
2015年

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

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 '16

67

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

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

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

还需要注意的是你永远不1个必要在这里引用大括号内。

1除非使用fish外壳。


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

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

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

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

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

27

假设您正在使用gnu find,则可以使用以下-delete选项:

find . -name test -delete

这更容易记住。


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

93
这不适用于非空目录。
belacqua

2
也可在Mac OS X上使用
2016年

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

选项顺序非常重要,因此请按顺序执行它们,-delete必须是最后一个选项
Jose Ignacio 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会出现“无此文件或目录”错误。要消除错误,您可以将stderr重定向到/ dev / null或将-frm标志与(强制)一起使用。


2
坏主意:用空格的文件名会引发各种可怕的问题
克莱门特

2
对于未来的读者:这find . -name "to-delete" -print0 | xargs -r0 -- rm -r是一种不会在空间上崩溃的防故障版本
Charlie

3
请参阅需要添加的unix.stackexchange.com/a/115869/8257-prune
Mapio

1
添加-prune以避免“没有这样的文件或目录”错误。
Julien Carsique '17

12

一种更快的方法是:

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

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


如果您要查找要与子目录一起删除的目录,那不是很有用。
亚历克西斯·威尔克

5

重击特定的解决方案:

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

3
请注意,对于与许多文件匹配的glob的命令行扩展,使用此机制可以匹配的文件数量是有限制的。超过此限制将导致bash: /bin/rm: Argument list too long
Drav Sloan

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

4

我发现该-delete动作在-path测试中确实可以很好地工作。例如,以下应该解决原始海报问题:

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

你确定吗?-delete意味着-depth,并且它肯定会删除我系统上的非空目录。
Magnus

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

我也尝试了这种方法,并且有效-目录已删除。
艾伦
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.