“ rm。*”是否会删除父目录?


53

.*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并且rm从中rm (GNU coreutils) 8.13获得以下消息:

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

这是GNU还是POSIX?是否有* nix个系统可以在其中默默地删除...

另外,这是外壳程序还是rm命令本身的安全功能?


4
我知道这个问题是在的情况下rm,但我认为这是值得一提的,你仍然可以有意想不到的效果chmodchown等匹配时.*
亚伦·科普利

Answers:


59

在POSIX规范的最新(2017年)版的rm效用是在这里(和前一个),禁止删除...

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

如@jlliagre所指出的,关于的部分/是SUSv4中的一个附加项。

最古老的公共可用规范的Unix,我能找到(XPF4 CAE转2(1994)),已指定了...不能被删除,但在GNU fileutils中的changelog言论表明它已经在旧的POSIX规范的情况。

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

历史

早期的大学

-r要选择rm在Unix的V3(1973)加入虽然它只是删除目录的内容,你仍旧需要使用rmdir,删除目录。

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

禁止删除该文件..只是为了避免因疏忽而执行类似操作的反社会后果rm -r .*

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

.尽管它不会取消链接...条目,但仍接受删除。因此,这rm -r .是清空当前目录的有效方法。

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

有趣的是,这已经解决了glob可能包含的错误/功能不全.以及..扩展的问题。这是固定的福塞斯壳在80年代末(原来为Minix的外壳和pdksh程序的基础),zsh(1990)和fish(2005),而不是其他炮弹,尤其是不POSIX的sh语言,需要扩大.*到包括...若它们由返回readdir()((bashshopt -s dotglob在glob(除glob之外.xxx)不包含.或的情况下部分解决了问题..,使用ksh可以解决此问题FIGNORE='@(.|..)'))。

何时.添加确切的禁止并不总是很清楚,并且每个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 Net / 1)。

为了这一天,在rm中的FreeBSD(和MacOS的类似衍生产品)仍然在清空当前或父目录rm -rf ./rm -rf ../虽然(事项rm -rf .*/)。

系统V

我没有太多信息,因为V7之后的AT&T Unix派生文件都没有公开可用的源代码或二进制文件。在其在线手册中,HPUX(基于System III)仍然提到它仅禁止..而有效地禁止两者,这表明至少SysIII可能不禁止删除.编辑:现在查看SysIII rm源代码,它是自Unix V7起几乎没有变化)。

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

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

GNU

GNU fileutils早期changelog具有所有历史信息。

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

其他

如我们所见,在中zsh.*(或任何全局)的扩展从不包含...(即使在sh仿真模式下)。因此,rm内置zmodload zsh/files函数(如果得到的话)将不被对待...特别对待。因此,使用该zsh内置函数,您可以rm -rf .rm -rf ..清空...,但rm -rf .*不会删除...

在busybox中rm,禁止删除...在0.52(2001)中添加


奇怪的是,这似乎表明rm -rf . /(注意空格)应打印两个警告(for ./)并退出,但似乎每隔几个月就会出现一个问题,问如何从中恢复。
凯文(Kevin)

6
@Kevin并非所有系统都符合POSIX,并且根目录限制仅在最新的POSIX版本中明确添加。
jlliagre 2013年

@jlliagre我明白了。GNU通常会尝试实现POSIX(当然是+扩展),我想他们会想将它放进去,但是如果它相当新,那就可以解释它。
凯文

2
@Stephane:您是对的,但我仍然会在回答的开头加上一个大的“是的,它可能会发生!但是...”,这样人们无疑会在某些(旧的或非旧的)上知道这一点。 -POSIX兼容)系统,它们可以删除父目录。我试图总是指出那些可能性(即,即使试图使答案有时难以阅读/记住,我也要尽量保持安全)^^
Olivier Dulac 2013年

1
@MartinSchröder,在BSD上,它是在2.8BSD和2.10BSD之间(在像UnixV7中一样仅禁止“ ..”之前)和3BSD和4.3RENO之间的某个地方添加的。在SysV系统上,这一点还不清楚。例如,HPUX手册声称它仅禁止“ ..”,但实际上它禁止两个“。”。和“ ..”,只是最新的手册。
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.