删除数百万个文件


38

我的目录充满了数百万个gif图像。rm命令太多。

我一直在尝试这样的find命令:

find . -name "*.gif" -print0 | xargs -0 rm

问题是,它使我的机器停顿得很不好,并且由于它是服务器,因此导致客户超时。

有什么方法可以更快地删除所有这些文件...而无需锁定机器?


使用下面的“ nice find”命令,删除速度约为6 gb / hr。可能要花48小时才能删除所有文件。发生这种情况的原因是b / ca scour脚本失败。我已经超越了–使用rm命令执行“事件范围”,然后就消失了

3
删除整个目录不会很快吗?只是拿出“好”文件,然后再
核对

好吧,现在每个文件都是坏文件,因为它已移至/ dir_old,并且我重新制作了/ dir。但是rmdir不会遇到与rm *相同的限制吗?

@Corepuncher:我期望移除整个目录(如rm -rf会更快这是值得一试。
杰森- [R

我当前在目录上运行“ rm -rf”。它已经运行了20多个分钟...磁盘大小尚未更改。但是它也没有自动返回“参数列表太长”。唯一的问题是,这真的是在砸我的机器并使其他东西变慢/失败。不知道要放多久。

Answers:


44

更快不一定是您想要的。您实际上可能希望运行慢一些,因此删除在运行时会占用较少的资源。

使用nice(1)降低命令的优先级。

nice find . -name "*.gif" -delete

对于受I / O约束的进程,nice(1)可能还不够。Linux调度程序确实考虑了I / O,而不仅仅是CPU,但您可能希望更好地控制I / O优先级。

ionice -c 2 -n 7 find . -name "*.gif" -delete

如果这样做没有效果,您还可以添加睡眠以真正减慢它的速度。

find . -name "*.gif" -exec sleep 0.01 \; -delete

3
哇...睡眠时间为.1 s的数百万个文件...需要一天的时间才能处理864000个文件。
glglgl

7
@glglgl好吧,聪明的屁股。我更改了超时时间。:-P
约翰·库格曼

28
睡眠可能是一个不错的选择,但不会做,因为这里的任务是IO绑定的,而不是CPU的;您可以改用ionice。请注意,如果睡眠时间太短,它将毫无用处。
Matteo Italia

3
@glglgl:关键是,如果您不希望导致服务器上的服务中断,则必须慢慢进行,这段代码休眠的时间就是让服务器对磁盘进行实际有用的工作。
Matteo Italia

1
+1为sleep添加项-尽管使用,但我在IO上阻塞服务器时遇到了麻烦ionice -c 3。它确实大大增加了清除文件所需的时间(当然),但是我宁愿等待而不是关闭应用程序……
Ola Tuvesson

22

由于您正在运行Linux,并且此任务可能受I / O限制,因此建议您使用以下命令为您的命令空闲I / O调度程序赋予优先级ionice(1)

ionice -c3 find . -name '*.gif' -delete

与您的原始命令相比,我认为通过避免使用管道连接甚至可以节省更多的CPU周期xargs


@Braiam是什么意思?这不是find ... -exec有意义的地方。

哦,是的,很抱歉。我的错。您确定这有效吗?
Braiam

1
好吧,find(1)文档声称是这样。:)很明显,让find自己删除文件比rm为此分叉命令更有效。

1
我已经在生产服务器上具有400万个文件的文件夹中尝试了几种建议的版本,而这是唯一不会阻塞系统的版本。ionice -c3降低IO,使其在IO空闲时仅运行即可,因此非常理想。请注意,由于-delete这不是标准的查找方法,因此您可以使用以下命令执行相同的操作(包括有效的反馈):ionice -c 3 find . -name '*.gif' -exec echo {} \; -exec rm {} \;-缓慢但没有重要过程的等待。
ChristopherLörken2015年

13

没有。

没有比磁盘软格式更快捷的方法了。这些文件提供给RM 一次(最多到命令行的限制,它可以也设置为xargs),这是为每个文件调用RM好得多。所以不,绝对没有更快的方法。

使用nice(或renice在正在运行的进程上)只能部分帮助,因为那是为了调度CPU资源,而不是磁盘!而且CPU使用率将非常低。这是linux的一个弱点-如果一个进程“吞噬”了磁盘(即可以很好地使用磁盘),则整个计算机都将卡住。修改后的内核以供实时使用可能是一个解决方案。

我在服务器上要做的是手动让其他进程执行其工作-包括暂停以使服务器保持“呼吸”状态:

find . -name "*.gif" > files
split -l 100 files files.
for F in files.* do
    cat $F | xargs rm
    sleep 5 
done

每100个文件后将等待5秒。这将花费更长的时间,但是您的客户不会注意到任何延迟。


“将文件一次交给rm(直到命令行的限制)” —因此,当命令shell命令时rm *,它将扩展*为包含所有文件名的行并将其传递给它rm?这真是愚蠢。为什么要shell扩展通配符吗?

:-D @Joker_vD,正如您的名字所示,您在开玩笑吗?:-)
Tomas

2
@Joker_vD:与1970左右的Unix决策兼容。Windows不会这样做。在那里,程序可以将通配符传递给FindNextFile / FindNextFile,因此它们一次获得一个结果。
MSalters 2013年

@Tomas在这种情况下不行。老实说,我立即看到这样的设计有两个问题:首先,命令行不是橡胶;其次,该程序无法告知是否使用*或调用了该程序,/*并且对该用户的这种选择表示​​怀疑。

1
@Joker_vD关于shell进行通配符扩展有很多好处。它与Windows不同,但是不要仅仅因为它与您以前的习惯不同而得出这样一个令人难以置信的愚蠢的结论。如果您想了解更多,我建议您谷歌搜索或在相关的Stack Exchange网站上发布问题。这对于此评论区域来说是一个巨大的出轨。
John Kugelman

5

如果要删除的文件数量大大超过了遗留的文件数量,那么走遍待删除文件树并进行所有这些文件系统更新可能不是最有效的方法。(这类似于执行笨拙的引用计数的内存管理,访问大树中的每个对象以删除其引用,而不是一步将所有不需要的内容放入垃圾中,然后遍历所有可清除的内容。)

也就是说,克隆要保留到另一卷的树的部分。在原始卷上重新创建一个全新的空白文件系统。将保留的文件复制回其原始路径。这模糊地类似于复制垃圾回收

会有一些停机时间,但是比持续的性能下降和服务中断更好。

在您的系统和情况下,这可能不切实际,但是很容易想到这是可行的明显情况。

例如,假设您要删除文件系统中的所有文件。逐个递归和删除的目的是什么?只需卸载它,然后在分区上方执行“ mkfs”,即可创建空白文件系统。

还是假设您想删除除六个重要文件以外的所有文件?从那里拿出六打,然后在上面放上“ mkfs”。

最终,当必须保留足够的文件时,会有一个收支平衡点,考虑到其他成本(如停机时间),进行递归删除会变得更便宜。


4

你有没有尝试过:

find . -name "*.gif" -exec rm {} +

末尾的+号将使find包含更多要执行的rm命令文件。检查此问题以获取更多详细信息。


它的执行速度比-print0快得多。xargs解决方案,因为不是针对每个文件而是针对大量文件调用rm进程,因此导致较低的负载。

@JohnKugelman是的,但是它是GNU扩展,并不总是与本机find命令一起使用。
CodeGnome

好吧,很有趣,但这是一件很新的事情(以及-delete),它不一定总是在那里
Tomas

但是,与OP的解决方案相比,这无疑带来了什么。
Tomas
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.