删除数百万个文件

Cor*_*her 38 linux bash shell rm find

我有一个目录,里面装满了数百万张 gif 图像。rm 命令太多了。

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

find . -name "*.gif" -print0 | xargs -0 rm
Run Code Online (Sandbox Code Playgroud)

问题是,它使我的机器非常糟糕,并且由于它是服务器而导致客户超时。

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

Joh*_*man 45

更快不一定是您想要的。您可能希望实际运行更慢,因此删除操作在运行时消耗的资源更少。

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

nice find . -name "*.gif" -delete
Run Code Online (Sandbox Code Playgroud)

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

ionice -c 2 -n 7 find . -name "*.gif" -delete
Run Code Online (Sandbox Code Playgroud)

如果这不起作用,您还可以添加一个睡眠来真正减慢它的速度。

find . -name "*.gif" -exec sleep 0.01 \; -delete
Run Code Online (Sandbox Code Playgroud)


小智 22

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

ionice -c3 find . -name '*.gif' -delete
Run Code Online (Sandbox Code Playgroud)

与您的原始命令相比,我想这甚至可以通过避免管道到xargs.


Tom*_*mas 14

不。

没有更快的方法,从磁盘的软格式化开始。这些文件提供给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
Run Code Online (Sandbox Code Playgroud)

这将在每 100 个文件后等待 5 秒。这将需要更长的时间,但您的客户不应注意到任何延迟。

  • @Joker_vD:与 1970 年左右的 Unix 决定的兼容性。Windows 不这样做。在那里,程序可以将通配符传递给 FindNextFile/FindNextFile,以便一次获得一个结果。 (2认同)

Kaz*_*Kaz 5

如果要删除的文件数量远远超过留下的文件数量,则遍历要删除的文件树并执行所有这些文件系统更新可能不是最有效的方法。(它类似于进行笨拙的引用计数内存管理,访问一棵大树中的每个对象以删除其引用,而不是一步将所有不需要的东西都变成垃圾,然后扫荡可到达的东西进行清理。)

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

会有一些停机时间,但这可能比持续糟糕的性能和服务中断要好。

这在您的系统和情况下可能不切实际,但很容易想象出明显的情况,这是要走的路。

例如,假设您想删除文件系统中的所有文件。一一递归和删除有什么意义?只需卸载它并在分区顶部执行“mkfs”以创建一个空白文件系统。

或者假设您想删除除六个重要文件之外的所有文件?把六个从那里拿出来......“mkfs”在上面。

最终,当有足够多的文件必须保留时,会出现一些盈亏平衡点,考虑到其他成本(如任何停机时间),执行递归删除的成本会降低。