[玩机滑铁卢] 记一次由Windows文件错误递归删除引起的重大事故,以及及对使用Win的Linux爱好者的忠告

我只是觉得应该备份数据而已,要保证随时把数据全删了都没问题

今天翻论坛又看到了挖坟这件惨事的帖子。我回想了一下,其实Linux下的软件重解析mklink后的文件源删除的行为是正确的啊

再来回顾一下,不论是mklink文件或者/d 参数产生的文件夹都是符号链接。本质上就是为了穿透这个路径点,对源文件操作。比如我对C盘下的TEMP文件夹重载到Z盘这个内存盘里的TEMP目录。只要在本机Windows环境下操作,它必然直接重解析访问源的z盘TEMP文件夹而不是c盘。这也是内存盘用来挂载临时文件夹的原理。

而带/j产生的junction交接点或者微软称之为软连接,在本机环境下和前边的符号链接并没有什么区别,所以你看的大Windows里这两者混用也很普遍,比如上古遗留的Document文件夹被junction到%USERNAME%文件夹保持向前兼容

两者的区别就是符号链接一般不强制指定参数是会写相对路径,而junction是写绝对路径。这个差异要在网络访问才看得出来,本机访问没有什么差异。比如之前的C盘下的TEMP文件夹,你用手机通过SMB共享访问,如果是符号链接,大概率你手机上没有这个Z:\TEMP所以访问出错,重解析不过去。而junction因为是绝对路径,还是能重解析到Z:\TEMP。你可以直接远程访问的时候通过UNC地址验证一下。

那话说回来你mklink /d时产生的是符号链接。本质上对除了明确不进行重载点的参数操作。对比如之前举例的C:\TEMP\xxx的文件操作必然重解析到Z:\TEMP\xxx头上去。

而对于C:\TEMP这个link。或者说虚假的挂载点文件夹。你对它本身的操作不论是重命名还是删除,仅对其本身生效,不会溯源操作Z:\TEMP。所以你直接上rm -rf当然操作到源上去,r参数就是要递归子目录啊!

再考虑到你的清理软件是wsl环境下的。通过UNC路径映射的回收站?那它对于回收站文件极大可能是递归操作了。当然会被系统解析到源文件。

而要避免这样的错误。要么在使用wsl软件访问本机目录时严格注意递归或者干脆关闭,要么对重解析点的文件,手工指明删除深度,切莫递归

1 个赞

我来补充一下,Windows 有软链、硬链和 junction 三个概念,而对于 Linux 来说,目录从来都是软链,没有硬链——有但被禁止了。Linux 也有 junction,但是一般很少用到,我最后再说这个事。

Linux 的软链是个啥呢?其实就是一个普通的文本文件,里面就一行内容,写上这个软链指向的路径,然后再加上一个软链的标志位。内核读到这个文件的时候,会特别处理一下,解析跳到目标目录去。注意这个机制会带来一个问题,就是你作为普通用户,可以随便创建一个软链,指向没有权限的目录。另外就是可以随便往这个文件里面写入任何内容,不只是路径,你写入 SQL 命令也没问题啊,内核能不能执行是另外一回事。

既然 Linux 的软链本质上是个文本文件。那么你们用rm symlink这条命令时,实际上就是删除了一个文本文件而已。你们再试一下rm symlink/这个命令,注意软链名字后面有个/,此时一定会报错,说这个是一个目录,你得用rm -fr symlink/才能完成把这个目录删掉。你们再次试验一下,会发现rm -fr symlink也只删链接,没有目录内容。

所以楼主的问题也来源于此,rm 在删软链时有两种方式,它们在 rm 命令里面被区分,区别是你最后有没有带一个/。前提是 rm 命令要检测出这是一个软链接。在 cygwin 环境或者一些粗心大意的软件里面,这可能检测不出来啊,于是整个目录内容就被删除了。

Windows 在删除目录链接时也同样两种方式,一种是只删除这个链接文件,另外一种是删除里面的内容。explorer 永远只有第一种方式,而 cmd 的 del 命令永远都是第二种。所以你们在 Windows 里面使用链接的时候一定一定要非常小心。

最后,Windows 的三种目录链接方式在 Linux 里面也都有:软链是ln -s命令;硬链是ln -d命令但都会报错;junction 其实是"mount -o rebind",只有 Linux 支持。

最后的最后,为什么要区别这三种方式呢?软链接的好处是文本文件内容其实可以随便填,比如既可以填绝对路径,也可以填相对路径,还可以填 UNC 路径指到网络, rt23i950 所说的它的内容在客户端被解析;硬链直接指向当前分区的另一个目录,解释速度最快;而 junction 其实是 ntfs 用于支持第三方文件系统的,可以任何扩展功能非常牛逼,但一般大家就用于挂另外一个分区小材大用了。

1 个赞

删除目录链接用rmdir不要带参数,而不要用del,就没有什么问题。

del本意就是删除指定路径下的文件,而非目录本身。Win 98以前的老版本带的del命令就有删除本级目录的bug,后来被修正了。

我的电脑不知道怎么捣鼓的留下了一个无限嵌套的文件夹,每个子文件夹的名字都不一样,查询了很多办法都不得解决,在看完你这个帖子的某一天,我看着鼠标右键文件夹的git bash here突发奇想,git好像用的就是linux的命令,然后尝试用rm命令删除那个文件夹,没想到一下子就成功了,今天刚好又看见你的新帖子,于是来这里说一嘴,你写的帖子对我很有帮助,谢谢你的分享 :yum:

1 个赞

我几年前看到贴吧上面有人说自己用360清理 Windows.old 文件夹,结果整个盘都被抹了一遍