cmd.exe 中的 del 或 erase 到底做了啥?

Posted

技术标签:

【中文标题】cmd.exe 中的 del 或 erase 到底做了啥?【英文标题】:What does del or erase in cmd.exe do under the hood?cmd.exe 中的 del 或 erase 到底做了什么? 【发布时间】:2016-09-22 05:54:16 【问题描述】:

我在 *** 上阅读了很多关于删除大量文件的最快方法的帖子。 What's the fastest way to delete a large folder in Windows? https://superuser.com/questions/19762/mass-deleting-files-in-windows/289399#289399 等等

根据我自己的测试,在 C# 代码中,通过网络删除文件的最快方法似乎是调用 cmd.exe 并使用 del /f/s/q

var before = DateTime.Now;

var cmd_line = "/c del /f/s/q \"" + Path.Combine(dir, num_to_delete.ToString()) + "\"";

var startInfo = new ProcessStartInfo("cmd", cmd_line)

    RedirectStandardError = true,
    RedirectStandardOutput = true,
    UseShellExecute = false

;

var process = new Process()  StartInfo = startInfo ;
process.Start();
process.WaitForExit();

var stdOut = process.StandardOutput.ReadToEnd();
var stdErr = process.StandardError.ReadToEnd();

var complete = DateTime.Now;

我的问题是,有没有办法确定 del 在幕后做了什么? Win32 中是否有我缺少的 API 可以直接调用而不是启动 cmd.exe?

我的代码是用 C# 编写的,但如果 C# 不提供此方法,我不介意调用一些东西。

我的测试方法如下:

创建一个名称为数字的文件夹(5、10、20,最多 10240) 在5下,创建文件夹1,放入1 100 KB文件 在5下,创建文件夹2,放入2 100 KB文件 以此类推,直到叶子下总共有 5 个文件。 然后将整个过程重复 10 次,以此类推

这让我可以创建大量文件来挖掘和删除一些。

我尝试的第一种删除方法基本上是(这使用像 \5\1_0, 2_0, 2_1 这样的结构)——即同一文件夹中的所有文件

string strFilePath = Path.Combine(dir, num_to_delete + "-*");
string strDirectory = Path.GetDirectoryName(strFilePath);
string strFileName = Path.GetFileName(strFilePath);

DateTime before, after, complete;

if (strDirectory != null && strFileName != null && Directory.Exists(strDirectory))

    int number_present = Directory.GetFiles(strDirectory).Length;

    before = DateTime.Now;
    string[] strFiles = Directory.GetFiles(strDirectory, strFileName);
    after = DateTime.Now;
    foreach (string strFile in strFiles)
    
        File.Delete(strFile);
    
    complete = DateTime.Now;

第二种删除方法使用结构5\1\、5\2\等。 string strDirectory = Path.Combine(dir, num_to_delete.ToString());

DateTime before, after, complete;

int number_present = Directory.GetFiles(dir).Length + Directory.GetDirectories(dir).Length;

before = DateTime.Now;
bool bExists = Directory.Exists(strDirectory);
after = DateTime.Now;
if(bExists)

    Directory.Delete(strDirectory, true);

complete = DateTime.Now;

第三种删除方法使用相同的结构,但将文件留在后面: 字符串 strDirectory = Path.Combine(dir, num_to_delete.ToString()); 字符串 strFilePath = Path.Combine(strDirectory, "*"); 字符串 strFileName = Path.GetFileName(strFilePath);

DateTime before, after, complete;
if (Directory.Exists(strDirectory))

    int number_present = Directory.GetFiles(strDirectory).Length;

    before = DateTime.Now;
    string[] strFiles = Directory.GetFiles(strDirectory, strFileName);
    after = DateTime.Now;
    foreach (string strFile in strFiles)
    
        File.Delete(strFile);
    
    complete = DateTime.Now;

第 4 个是您在顶部看到的那个。

我的发现是在160个文件大小之后,按速度顺序一次删除5个文件:

4th (del /f/s/q) 1st(从一个大文件夹中删除文件) 2nd(从子文件夹中删除文件,但保留文件夹) 3rd(从子文件夹中删除文件并离开子文件夹)

我将所有测试运行了 3 次,然后在 excel 中对结果进行平均,然后绘制图表。我认为我的数值分析是正确的。

【问题讨论】:

为什么你认为这很快?你是怎么衡量的? 您是否将其与 File 和 Directory 类的可读性更强的内置方法进行了比较? 在后台,cmd 使用 DeleteFile。 .NET 框架使用the same method。因此,它们都应该执行相同的操作。我的直觉告诉我你没有正确测量速度。 在这里使用Stopwatch 会更准确吗? 测量性能还取决于发布版本与调试版本 (***.com/questions/4043821/…),独立运行或在调试器下运行,编译为 32 位与 64 位(与 CMD 相比),. .. 【参考方案1】:

您可以使用Rohitab API monitor 来了解 CMD 在内部执行的操作。 CMD 是 Windows 64 位上的 64 位进程,所以你要更喜欢 64 位版本。

对于本地文件的删除,CMD 使用GetFileType()、GetCurrentDirectory()、GetVolumeInformation()、GetFileAttributes()、GetFullPathName()、FindFirstFileEx()、DeleteFile() 和FindClose()。我通过检查 API 部分 Data Access and StorageDevices 捕获了这一点。

删除网络共享上的项目时,您可以尝试网络/网络共享管理

我假设 .NET 在内部使用相同的功能。为什么它还要做任何事情?

【讨论】:

看起来如果您查看 Directory.Delete 的源代码(例如),它不会在循环中使用 findfirstfileex,它会递归。可以稍微优化该功能。我会试试那个工具,谢谢

以上是关于cmd.exe 中的 del 或 erase 到底做了啥?的主要内容,如果未能解决你的问题,请参考以下文章

windows的cmd里面的对文件的del和erase有啥区别?

del命令

如何使用 psexec 向远程计算机上启动的 cmd.exe 提供多个命令

C++ STL中erase函数的用法 求助~~

C++ STL中erase函数的用法 求助~~

dos系统删除命令大全