删除目录中所有文件和子文件夹的最快方法是什么?

删除目录中所有文件和子文件夹的最快方法是什么?

一个程序创建了许多嵌套的子文件夹。我尝试使用命令 rm -fr *将它们全部删除。但速度非常慢。我想知道有没有更快的方法来删除它们?

答案1

从该目录中删除它们的最快方法是将它们移出那里,然后只需在后台删除它们即可:

mkdir ../.tmp_to_remove
mv -- * ../.tmp_to_remove
rm -rf ../.tmp_to_remove &

这假设您的当前目录不是某些已安装分区的顶层(即../.tmp_to_remove位于同一文件系统上)。

如果您有任何以--.mv-

上面的代码会在不到一秒的时间内从当前目录中删除文件,因为它不必递归地处理子目录。从文件系统中实际删除树需要更长的时间,但由于它不碍事,因此其实际效率应该不那么重要。

答案2

rsync出奇的快速和简单。您必须先创建空目录,

mkdir 空目录
rsync -a --删除空目录/你的目录/

yourdirectory/是您要从中删除文件的目录。

答案3

最快的是rm -rf dirname.我在 RedHat6.4 上使用了 ext3 文件系统的快照挂载点,其中包含 140520 个文件和 9699 个目录。如果rm -rf *很慢,可能是因为您的顶级目录条目有地段文件,并且 shell 正忙于扩展*,这需要额外的 readdir 和 sort。转到目录并执行rm -rf dirname/.

Method                    Real time    Sys time  Variance (+/-)
find dir -delete          0m8.108s     0m3.668s  0.055s
rm -rf dir                0m7.956s     0m3.640s  0.081s
rsync -delete empty/ dir/ 0m8.305s     0m3.918s  0.029s

笔记:

  • rsync版本:3.0.6
  • rm/coreutils 版本:8.4-19
  • 查找/findutils版本:4.4.2-6

答案4

的一个问题rm -rf *,或更正确的等价物rm -rf -- *是,shell 首先列出当前目录中的所有(非隐藏)文件,对它们进行排序并将它们传递给rm,如果当前目录中的文件列表很大,则为会增加一些不必要的额外开销,如果文件列表太大,甚至可能会失败。

通常,您会这样做rm -rf .(这也有删除隐藏文件的好处)。但大多数rm实现(包括所有符合 POSIX 的实现)将拒绝这样做。原因是某些 shell(包括所有 POSIX shell)具有 glob 扩展.*将包含.和的错误功能..。这意味着rm -rf .*将删除当前目录和父目录,因此rm已进行修改以解决这些 shell 的错误功能。

有些贝壳pdksh(以及其他福赛斯贝壳衍生物),zsh或者fish没有这种错误特征。zsh有一个rm内置的,您可以启用autoload zsh/files它,因为zsh's.*不包含...不能与 一起使用rm -rf .。所以在 中zsh,你可以这样做:

zmodload zsh/files
rm -rf .

在 Linux 上,您可以执行以下操作:

rm -rf /proc/self/cwd/

清空当前目录或:

rm -rf /dev/fd/3/ 3< some/dir

清空任意目录。

(注意后面的/

在 GNU 系统上,您可以执行以下操作:

find . -delete

现在,如果当前目录只有几个条目,并且大部分文件都在子目录中,那么这不会产生显着差异,并且rm -rf -- *可能是您可以获得的最快速度。预计rm -rf(或删除每个文件的任何内容)都会很昂贵,因为这意味着读取所有目录的内容并调用unlink()每个条目。unlink()它本身可能非常昂贵,因为它涉及修改已删除文件的索引节点、包含该文件的目录以及某些文件系统映射或其他可用区域。

rm并且find(至少 GNU 实现)已经按每个目录中的 inode 编号对文件列表进行排序,这可以在 ext4 文件系统上的性能方面产生巨大差异,因为它减少了连续(或彼此接近) inode 按顺序修改。

rsync按名称对文件进行排序,这可能会大大降低性能,除非按名称顺序恰好与按 inum 顺序匹配(就像从文件名排序列表创建文件时一样)。

在某些情况下可能更快的原因之一是,它似乎没有采取安全预防措施来避免竞争条件,如果目录在工作时被符号链接替换,则rsync可能导致它进入错误的目录。rmfind

进一步优化:

如果您知道目录树的最大深度,您可以将其传递给find

find . -maxdepth 3 -delete

这样就find不必尝试读取深度 3 的目录内容。


¹ 另请参阅globskipdotsbash 5.2+ 中的选项

相关内容