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 Storage 和 Devices 捕获了这一点。
删除网络共享上的项目时,您可以尝试网络/网络共享管理。
我假设 .NET 在内部使用相同的功能。为什么它还要做任何事情?
【讨论】:
看起来如果您查看 Directory.Delete 的源代码(例如),它不会在循环中使用 findfirstfileex,它会递归。可以稍微优化该功能。我会试试那个工具,谢谢以上是关于cmd.exe 中的 del 或 erase 到底做了啥?的主要内容,如果未能解决你的问题,请参考以下文章
windows的cmd里面的对文件的del和erase有啥区别?