如果我想清空一个目录,有什么理由不应该删除它并重新创建它?

If I want to empty a directory, is there any reason I shouldn't remove it and recreate It?

我查看了这两个用于清空目录的线程:

然而,清空目录的函数非常复杂,一个答案可能会遇到堆栈溢出。

当我考虑删除和添加目录时,我正在考虑用 C 语言在 Linux 平台上进行。但是,如果您还想在 Windows 上解释这背后的原因,我也将不胜感激。 这是我要实现的代码:

system( "rm -rf /some/directory" )
mkdir("/some/directory", 0700);

这看起来简单多了。我有什么理由不使用它?它的效率远不如表面上看吗?

rm -fr /some/directory 命令必须为您完成递归工作。使用命令比编写自己的代码来完成相同的工作要简单得多——它体现了惰性的优点,并在程序规模上利用了代码重用。 (您不能在目录上使用 rmdir() 系统调用,除非它已经是空的。)。所以这并非完全不合理。

一个问题是安全性:有人可以在您的路径上放置系统 rm 命令的替代方法吗?在 Unix 上,/bin/usr/bin 在您的路径中是第一个,还是其他目录在第一个?

如果您认为使用 /bin/rm(或 /usr/bin/rm)足够安全,那么这可能是比朴素的 rm 更好的选择,但总的来说,这还不够不好。

另一个问题是安全性的另一个方面——您真的可以删除并创建目录吗?能不能写成/some?如果您删除并重新创建 /some/directory,您是否应该保留其当前所有者、组和权限?在这些操作之后,该目录将由进程的有效 UID 拥有; if 将属于具有进程有效 GID 的组(除非 /some 目录上设置了粘性位——或者除非你使用的是 macOS);并且权限将是 0777,由 umask() 的当前设置修改。

如果这些问题不重要,或者是可以规避的,那么删除并重新创建是合理的。


扩展以上评论:

When you mentioned the system() call in your comment, I had no idea what you were talking about.

system() 函数执行通过命令解释器作为参数传递的字符串。当您编写代码时,您必须考虑当恶意的人试图获取您的代码时它会怎样出错 运行。当你写 "rm -fr /some/directory" 时,你依赖于 shell 找到正常的 rm 命令并正常工作。但是,如果您的 PATH 具有诸如 $HOME/bin:/bin:/usr/bin 的值(以便优先使用您自己的私有 bin 目录中的命令而不是系统提供的命令),那么如果用户可以将他们自己的脚本安装为 $HOME/bin/rm,他们可以使用您的权限执行任意代码——这可能允许他们留下一种方法来侵入您的系统,然后保留您拥有的所有权限。他们甚至可能会清除(大部分)曾经存在 $HOME/bin/rm 脚本的证据。

避免此类问题的一种方法是请求 "/bin/rm -fr /some/directory"(当然,除非 rm/usr/bin 而不是 /bin)。这可以说更安全。过去可以通过 IFS 环境变量进行攻击;这些被现代 shell 绝育了,它们不使用 IFS.

的任何继承值

请注意,一个问题是解释 rm 命令是否成功。 -fr 选项意味着它将在几乎所有情况下报告成功 — 但如果目录没有消失,您的 mkdir("/some/directory", 0777) 调用将失败。

As for the security of the /some/directory, my understanding of what you're trying to say, is that the wrong directory could be selected. I just can't imagine how that would occur.

假设您确实有权修改 /some 目录(您需要该权限才能删除 /some/directory),并且您可以修改所有 sub-directories /some/directory 的旧版本,那么您可能会从用户 victim、组 witless 拥有的 /some/directory 和权限 775 开始,而在命令和系统调用之后(请注意system() 是一个函数而不是系统调用;mkdir() 是一个系统调用)都成功了,该目录可能由用户 victor、组 mischief 拥有并具有权限 0777 . 这可能不太理想。如果您不想破坏此类权限设置,您可能不想使用删除和重新创建技术 — 或者,不是本示例所示的 simple-minded 技术。然后,您将不得不更加努力地删除目录的内容而不修改这些属性。您可以扫描目录 (opendir()readdir()closedir() 并在每个名称(或名称集)上调用 rm 以彻底清理而不删除目录本身。这具有混合复杂性。它比简单地删除和重新创建更繁琐,但远不如处理多个级别的完全递归删除那么繁琐。

正如我之前所说,您必须决定这些问题是否重要。重要的是您要意识到问题的存在,并且您已就是否处理这些问题以及如何处理这些问题做出有意识(且知情)的决定。

请记住,如果您的程序可能 运行 具有 root(管理员)权限,那么请务必小心——但即使只有普通普通用户会 运行,这仍然很重要程序。