从目录中删除数十亿个文件,同时查看进度

Jun*_*ooq 43 rm progress-information

我有一个 30 TB 的目录,里面有数十亿个文件,这些文件正式都是 JPEG 文件。我正在删除这样的文件的每个文件夹:

sudo rm -rf bolands-mills-mhcptz
Run Code Online (Sandbox Code Playgroud)

这个命令只是运行并且不显示任何它是否工作。

我想看看它正在删除文件或命令的当前状态。

les*_*ana 103

您可以使用rm -v具有rm打印一行每个文件删除。这样您就可以看到rm确实在删除文件。但是,如果您有数十亿个文件,那么您只会看到rm仍在运行的文件。您将不知道已经删除了多少文件以及还剩下多少文件。

该工具pv可以帮助您进行进度估算。

http://www.ivarch.com/programs/pv.shtml

这里是你将如何调用rmpv使用示例输出

$ rm -rv dirname | pv -l -s 1000 > logfile
562  0:00:07 [79,8 /s] [====================>                 ] 56% ETA 0:00:05
Run Code Online (Sandbox Code Playgroud)

在这个人为的例子中,我告诉pv过有1000文件。的输出pv显示已经删除了 562 个,经过的时间是 7 秒,估计在 5 秒内完成。

一些解释:

  • pv -l使得pv通过换行,而不是字节数
  • pv -s number告诉pv你总数是多少,以便它可以给你一个估计。
  • 最后的重定向logfile是为了干净的输出。否则,来自 的状态行pv会与来自 的输出混淆rm -v。奖励:您将拥有已删除内容的日志文件。但要注意文件会变得很大。/dev/null如果不需要日志,也可以重定向到。

要获取文件数,您可以使用以下命令:

$ find dirname | wc -l
Run Code Online (Sandbox Code Playgroud)

如果有数十亿个文件,这也可能需要很长时间。您也可以pv在此处使用以查看它计数了多少

$ find dirname | pv -l | wc -l
278k 0:00:04 [56,8k/s] [     <=>                                              ]
278044
Run Code Online (Sandbox Code Playgroud)

这里说计算 278k 个文件需要 4 秒。末尾 ( 278044)的确切计数是 的输出wc -l

如果您不想等待计数,那么您可以猜测文件的数量或使用pv而无需估计:

$ rm -rv dirname | pv -l > logfile
Run Code Online (Sandbox Code Playgroud)

像这样,您将无法估计完成,但至少您会看到已经删除了多少文件。/dev/null如果您不需要日志文件,请重定向到。


挑剔:

  • 你真的需要sudo吗?
  • 通常rm -r足以递归删除。不需要rm -f

  • @StephenKitt 这就是 Windows 文件实用程序真正让我(和许多其他人)烦恼的地方:它*总是*在删除文件之前计算文件的数量和大小,除非驱动器比处理器*慢得多* , 几乎和实际删除一样长! (7认同)
  • @StephenKitt 也许我错了,但除了磁盘访问之外,终端输出不是瓶颈吗?我相信 `pv` 每秒只刷新一次进度条,尽管它有输入。因此,终端只需要每秒显示一行而不是一吨。`pv` 只需要为它遇到的每个换行符增加一个计数器;这必须比做换行更快,以及在终端中显示一行的速度。我认为像这样使用 `pv` 会导致文件删除比简单的 `rm -rv` 更快。 (7认同)
  • 很好地使用`pv`,假设计算数十亿个文件并不太昂贵;-)。(它可能需要几乎与它应该测量的 `rm` 一样多的时间!) (5认同)
  • @skywinder `rm -rv 目录名 | pv -l -s $(find dirname | wc -l) &gt; 日志文件` (2认同)

Ste*_*itt 28

查看lesmana 的答案,它比我的好得多——尤其是最后一个pv例子,rm如果你指定/dev/null而不是logfile.

假设您rm支持该选项(因为您运行的是 Linux,它可能支持),您可以使用-v以下命令在详细模式下运行它:

sudo rm -rfv bolands-mills-mhcptz
Run Code Online (Sandbox Code Playgroud)

正如许多评论者指出的那样,由于终端生成和显示的输出量,这可能会非常慢。您可以改为将输出重定向到文件:

sudo rm -rfv bolands-mills-mhcptz > rm-trace.txt
Run Code Online (Sandbox Code Playgroud)

并观察 的大小rm-trace.txt

  • 这实际上会减慢删除速度,因为所有输出都被生成并呈现到终端:) (5认同)
  • 当然会变慢。将数十亿行写入文件不会在零时间内发生。 (2认同)

Pet*_*des 23

另一种选择是观察文件系统上的文件数量减少。在另一个终端中,运行:

watch  df -ih   pathname
Run Code Online (Sandbox Code Playgroud)

使用的 inode 数量会随着rm进度而减少。(除非文件大多有多个链接,例如,如果树是用 来创建的cp -al)。这会根据文件(和目录)数量跟踪删除进度。 dfwithout-i将跟踪使用的空间。

您还可以运行iostat -x 4以查看每秒的 I/O 操作(以及 kiB/s,但这与纯元数据 I/O 不太相关)。


如果您对rm当前正在处理的文件感到好奇,您可以将一个附加strace到它并观察unlink()(和 getdents)系统调用在您的终端上喷涌。例如sudo strace -p $(pidof rm)。你可以^crm不中断它的情况下分离它。

我忘记了是否rm -r将目录更改为要删除的树;如果是这样,你可以看看/proc/<PID>/cwd。它/proc/<PID>/fd可能经常打开一个目录 fd,因此您可以查看该目录以了解您的rm进程当前正在查看的内容。

  • `df -ih` 确实是一种观察 `rm` 进度的廉价方式。 (2认同)

Hit*_*eek 5

虽然上述答案都使用rm,rm实际上在删除大量文件时可能会相当慢,正如我最近观察到的那样,从 .tar 存档中提取 ~100K 文件时实际上比删除它们花费的时间更少。尽管这实际上并没有回答您提出的问题,但解决您的问题的更好方法可能是使用不同的方法来删除您的文件,例如此问题的已投票答案之一。

我个人最喜欢的方法是使用rsync -a --delete. 我发现这个方法执行得足够快,以至于它比该问题最受好评的答案更易于使用,其中作者编写了一个您需要编译的 C 程序。(请注意,这会将正在处理的每个文件输出到 stdout,很像rm -rv;这可能会大大减慢进程速度。如果您不想要此输出,请使用输出rsync -aq --delete或将输出重定向到文件。)

该答案的作者说:

该程序现在(在我的系统上)将在 43 秒内删除 1000000 个文件。与此最接近的程序是 rsync -a --delete,它花费了 60 秒(它也按顺序进行删除,但不执行有效的目录查找)。

我发现这对于我的目的来说已经足够好了。该答案也可能很重要,至少如果您使用的是 ext4:

作为一种预见,人们应该删除受影响的目录并在之后重新创建它。目录的大小只会增加,并且由于目录的大小,即使里面只有几个文件,性能也可能会很差。