如何在 Windows 上删除大量文件

Jac*_*ung 25 windows file-management

我有一个包含数百万个子目录和数万亿个文件的目录。现在我必须清除它。说万亿,我说的不是文件大小,而是文件数量。

我尝试使用del/s, 并使用 Windows 资源管理器删除它。都不能完成任务。我试过一个一个地删除一些子目录,这花了我几天时间。我遇到的问题是,每次无论使用del还是Explorer,在任务管理器中都可以看到explorer实例消耗天量内存,逐渐导致我的系统崩溃。

还有数亿个文件要删除。有没有可能用一个(或几个)命令/动作来实现?


[编辑]

我试过用 Cygwin 做它rm -fr,并产生了相同的结果。总结为:

  1. 无论使用Windows资源管理器,DEL从命令提示符,还是Cygwinrm命令,系统内存都会逐渐降为零,最终会导致盒子崩溃。

  2. 如果在任何时候,在系统失败之前,进程被关闭(通过 CTRL+C 或其他什么),该框将继续正常工作。但是,所有使用的内存都不会被释放。比如说,我在系统内存达到 91% 时停止了进程,任务管理器告诉:总共 4G RAM,缓存是 329M,可用 335MB。然后内存使用量将保持在这个水平,直到我重新启动机器。如果我在任务管理器中停止资源管理器实例,屏幕将变为空白,硬盘灯一直亮着,并且永远不会回来。通常,当我在任务管理器中停止资源管理器实例时,我可以通过按 Win+E 重新调用它,或者它会自动重新启动。

嗯,非常好的内存管理!


[再次编辑] 似乎在很长一段时间后确实释放了一些使用过的内存,但不是全部。一些缓存和可用内存确实在任务管理器中返回。我没有再等,不知道接下来会发生什么。

Syn*_*ech 10

技术说明

大多数方法导致问题的原因是 Windows 尝试枚举文件和文件夹。这对于几百甚至几千个文件/文件夹几级深并不是什么大问题,但是当数以百万计的文件夹中有数万亿个文件进入几十级深时,那肯定会使系统陷入困境.

让我们“只有” 100,000,000 个文件,Windows 使用这样的简单结构来存储每个文件及其路径(这样可以避免单独存储每个目录,从而节省一些开销):

struct FILELIST {                   // Total size is 264 to 528 bytes:
  TCHAR         name[MAX_PATH];     // MAX_PATH=260; TCHAR=1 or 2 bytes
  FILELIST*     nextfile;           // Pointers are 4 bytes for 32-bit and 8 for 64-bit
}
Run Code Online (Sandbox Code Playgroud)

根据它是使用 8 位字符还是 Unicode 字符(它使用 Unicode)以及您的系统是 32 位还是 64 位,那么它将需要 25GB 到 49GB 的内存来存储列表(这是一个非常简化结构)。

究其原因,为什么Windows会尝试删除前枚举文件和文件夹取决于您使用删除它们的方法,但两者资源管理器和命令解释器做(你可以看到的延迟,当您启动命令)。当它从驱动器读取目录树时,您还可以看到磁盘活动(HDD LED)闪烁。

解决方案

处理这种情况的最佳选择是使用删除工具,一次一个地删除文件和文件夹。我不知道是否有任何现成的工具可以做到这一点,但应该可以通过一个简单的批处理文件来完成。

@echo off
if not [%1]==[] cd /d %1
del /q *
for /d %%i in (*) do call %0 "%%i"
Run Code Online (Sandbox Code Playgroud)

它的作用是检查是否传递了参数。如果是这样,那么它会更改为指定的目录(您可以在没有参数的情况下运行它以在当前目录中启动或指定一个目录——甚至在不同的驱动器上让它从那里启动)。

接下来,它会删除当前目录中的所有文件。在这种模式下,它不应该枚举任何内容而只是删除文件而不会占用太多内存(如果有的话)。

然后它枚举当前目录中的文件夹并调用自己,将每个文件夹传递给它(self)以向下递归。

分析

应该起作用的原因是因为它没有枚举整个树中的每个文件和文件夹。它根本不枚举任何文件,只枚举当前目录中的文件夹(加上父目录中的其余文件夹)。假设任何给定文件夹中只有几百个子目录,那么这应该不会太糟糕,而且肯定比枚举整个树的其他方法需要更少的内存。

您可能想知道使用/rswitch 而不是使用(手动)递归。这是行不通的,因为当/rswitch 进行递归时,它预先枚举了整个目录树,这正是我们想要避免的;我们想在不跟踪的情况下随时删除。

比较

让我们将此方法与完整枚举方法进行比较。

你说过你有“数百万个目录”;让我们说一亿。如果树是近似平衡的,假设每个文件夹平均大约有 100 个子目录,那么最深的嵌套目录大约向下四层——实际上,整个树中将有 101,010,100 个子文件夹。(有趣的是 100M 如何分解为 100 和 4。)

由于我们不枚举文件,因此我们只需要跟踪每个级别最多 100 个目录名称,4 × 100 = 400在任何给定时间最多跟踪目录。

因此,内存要求应该是 ~206.25KB,完全在任何现代(或其他)系统的限制范围内。

测试

不幸的是(?)我没有一个在数百万个文件夹中包含数万亿个文件的系统,所以我无法测试它(我相信最后统计,我有大约 800K 个文件),所以其他人将不得不尝试它。

警告

当然,内存并不是唯一的限制。驱动器也将是一个很大的瓶颈,因为对于您删除的每个文件和文件夹,系统都必须将其标记为空闲。值得庆幸的是,许多这些磁盘操作将捆绑在一起(缓存)并以块的形式写出而不是单独写出(至少对于硬盘驱动器,而不是对于可移动媒体),但它仍然会在系统读取时引起相当多的颠簸并写入数据。


小智 10

我无法处理数以万亿计的文件,但我最近使用以下方法核爆了一个包含约 180 万个文件的旧文件共享:

robocopy EmptyTMPFolder FolderToDelete /MIR /MT:16 /ETA /R:30 /W:5
Run Code Online (Sandbox Code Playgroud)

“EmptyTMPFolder”是一个空的本地目录。/MIR 选项将使目标看起来像源(空)。

这种方法的真正好处是重试选项 (/R:30)。这为解决此过程中可能发生的任何连接问题提供了机会。本地删除可能不会在这种方法中找到好处。

我没有特定的基准来比较时间,但与重试/等待选项的其他一些建议 b/c 选项相比,我更喜欢这个。删除几乎立即开始。


soa*_*dos 5

删除所有文件夹需要很长时间,而且您无能为力。您可以做的是保存数据并格式化驱动器。它不是最佳的,但它会起作用(并且很快)。

另一种选择可能是在可以从 NTFS 分区读取的实时 CD 上使用一些 linux 发行版。我从个人经验中知道,它rm -rf folderName可以运行至少 2 天而不会使具有 2GB RAM 的系统崩溃。这将需要一段时间,但至少会完成。


Bob*_*Bob 5

呃..我不想知道你是如何创造这么多的。

发生的情况是,资源管理器在开始删除之前尝试枚举每个文件,并将信息存储在内存中。而且显然数量太多了。

你尝试过命令吗rmdir /s?只要它实际上在找到文件时将其删除,而不是等待每个文件都被枚举,它就可以工作。

子目录有多少级?如果只有一个或其他一些较小的数字,则手动递归的快速批处理文件可能会起作用。

不过,任何方法都需要一段时间。