'rm .*' 是否删除过父目录?

'rm .*' 是否删除过父目录?

该表达式.*由 bash 扩展以包含当前目录和父目录:

$ ls -la
total 2600
drwxrwxrwx   2 terdon terdon 2162688 Sep 10 16:22 .
drwxr-xr-x 142 terdon terdon  491520 Sep 10 15:34 ..
-rw-r--r--   1 terdon terdon       0 Sep 10 16:22 foo
$ echo .*
. ..

如果我rm -rf .*使用 GNU bash 在 Debian 上运行,version 4.2.36(1)-release并且rmrm (GNU coreutils) 8.13,我会收到以下消息:

$ rm -rf .*
rm: cannot remove directory: `.'
rm: cannot remove directory: `..'

这是 GNU 的东西还是 POSIX 的东西?是否有任何 *nix 系统,上面的命令会静默删除...

另外,这是 shell 或rm命令本身的安全功能吗?

答案1

该实用程序的 POSIX 规范的最新版本(截至 2017 年)rm这里(还有上一篇那里) 并禁止删除...

如果文件 dot 或 dot-dot 被指定为操作数的基名部分(即最终路径名部分),或者如果操作数解析为根目录,则 rm 应将诊断消息写入标准错误并且不执行任何操作更多这样的操作数。

正如 @jlliagre 所指出的,有关的部分/是 SUSv4 中的新增内容。

我能找到的最古老的公开可用的 Unix 规范(XPF4 CAE 修订版2(1994)),已经指定了这一点.并且..无法删除,尽管 GNU fileutils 变更日志中的注释表明旧的 POSIX 规范中已经存在这种情况。

请注意,它也适用于dir/..../,但某些实现(包括 UNIX 认证的实现,如 Solaris 11 和 macOS)仍然无法防范rm -rf ../rm -rf .*/)。

历史

早期的unices

-rUnix V3 (1973) 中添加了选项,尽管rm它只是删除目录的内容,但您仍然需要使用rmdir它来删除目录。

这种情况在 Unix V7(1979 年,该版本还引入了 Bourne shell,大多数 Unices 都源自该版本)中发生了变化。rm -r现在也删除了目录并且不会删除..目录树。这手册页状态:

禁止..仅仅为了避免无意中做类似的事情而造成反社会后果而删除该文件rm -r .*

(尽管有人可能会说这rm -r .*仍然是反社会的因为它删除了所有内容,因为.包含在内)。

它仍然接受删除,.但不会取消链接...条目。那么,rm -r .清空当前目录是一个有效的方法。

另请注意,保护措施仅适用于字面..参数,而不适用于dir/..or ./..。因此,rm -rf ./.*仍然会递归地删除父目录中的所有内容。

有趣的是,这已经解决了 glob 可以在其扩展中包含.和的错误/错误功能。这个问题在 80 年代末(1990 年)和(2005 年)..的 Forsyth shell(原始 Minix shell 和 pdksh 的基础)中得到了修复,但其他 shell 没有,特别是 POSIX语言,需要扩展来包含和if它们由(仅解决部分问题,其中 glob(除了那些)不包含or ,并且使用,您可以通过执行来修复它)。zshfishsh.*...readdir()bashshopt -s dotglob.xxx...kshFIGNORE='@(.|..)'

何时.添加确切的禁止并不总是很清楚,并且随每个 Unix 的不同而变化。以下是一些发现。

BSD

.在 2.9BSD (1983) 和 2.10BSD (1987) 以及 4.2BSD (1983) 和 4.3BSD (1986) 之间的某个时间添加了禁止(参见此更改在 unix-history-repo 中的时间戳为 1985)。

$ wget -qO- http://www.tuhs.org/Archive/PDP-11/Distributions/ucb/2.9BSD/root.tar.gz |
    zgrep -ao 'rm: canno[[:print:]]*'
rm: cannot remove `..'
$ wget -qO- http://www.tuhs.org/Archive/PDP-11/Distributions/ucb/2.10bsd.tar.gz |
    zgrep -ao 'rm: canno[[:print:]]*'
rm: cannot remove `.' or `..'
rm: cannot remove `.' or `..'\n");

对于dir/.dir/..,请参阅1988年的这一变化(BSD 4.3 网络/1)。

迄今为止,rmFreeBSD(以及 macOS 等衍生产品)的 仍然会清空当前目录或父目录rm -rf ./rm -rf ../对于 而言很重要rm -rf .*/)。

系统V

我没有太多信息,因为 V7 之后的 AT&T Unix 衍生品的源代码或二进制文件均未公开可用。在其在线手册中,HPUX(基于 System III)仍然提到它只禁止,..但实际上它禁止两者,这表明至少 SysIII 可能没有禁止删除.编辑: 现在正在看SysIIIrm源代码,自 Unix V7 以来几乎没有变化)。

我检查过的所有其他在线手册都提到删除...禁止,这应该符合 POSIX 标准。

Solaris仍然清空或rm上的当前目录或父目录。rm -rf ./rm -rf ../

GNU

GNU fileutils 的早期变更日志拥有所有历史信息。

虽然最初既不删除.也不..禁止,但..先被禁止,然后两者(包括dir/.),都在 1990 年至 1991 年间。

其他

正如我们所看到的,在 中zsh,(或任何 glob)的扩展.*从不包含...(即使在sh模拟模式下)。因此,内置函数rm(如果你这样做的话,你会得到它zmodload zsh/files)不会被特殊.对待..。因此,使用该zsh内置函数,您可以rm -rf .orrm -rf ..清空.or ..,但rm -rf .*不会删除.or ..

busybox 0.52 (2001) 中增加了rm禁止删除.和的功能..

相关内容