站在上面移除“。”

站在上面移除“。”

在摆弄文件系统时,我尝试了以下操作:

mkdir a
cd a
rmdir .

其结果是:

rmdir: failed to remove ‘.’: Invalid argument

好吧,先生rmdir,让我比你聪明一点:

rmdir ../a

...好的。

什么?这次没有错误?

我的终端仍然显示我在目录中a,但未ls -a列出任何内容(也.没有..),但ls ..仍可pwd按预期工作。

我是不是就像那些卡通人物一样,自己砍断了树枝却还没有倒下?

如果我尝试

mkdir ../a

它创建了一个目录a,但这仍然不是我所在的目录(ls -a .ls -a ../a显示不同的结果)。

如果我尝试使用它创建一个文件,touch b则会回复:

touch: cannot touch ‘b’: No such file or directory

touch .有效。

最后,一旦我离开我的目录,它就会消失并且我无法返回它。

编辑:有人能解释一下这里发生了什么吗?这种情况有名字吗?这是文件系统和 Bash 之间的问题,还是 Bash 中的一些特殊硬编码行为?

答案1

这与 bash 无关。

这是几十年前 Unix 的标准行为。这是内核的标准行为,与 shell 无关。

需要记住的重要一点是文件和目录不必有名称。只要 (a) 链接数不为零、(b) 由打开的文件描述符引用,或 (c) 是进程的工作目录,文件或目录就会一直存在。(还有其他几个条件可以防止文件或目录消失,但它们与您的问题无关。)

对于文件,您应该习惯于创建一个未命名的临时文件,当最后一个打开的文件描述符关闭时,该文件会自动清除,方法是打开一个文件然后取消链接,以便其链接计数降至零。 (这掩盖了许多与这个问题无关的安全相关细节。)

你也应该习惯于这样的想法:你可以取消链接某个进程具有打开的文件描述符的文件,创建一个同名的新文件,然后它们将被两个不同的文件

你只是对目录做了同样的事情。你清空了目录并取消了链接,但它继续存在,直到它不再被打开的文件描述符引用,也不再是任何进程的工作目录。当你用你取消链接的同名名称创建一个新目录时,你就两个不同的目录

请注意,如果命名的目录是任何进程的当前目录,SUS 可能rmdir ../a会失败。(这并不是像某些人认为的那样,给 Windows NT 上的 POSIX API 提供漏洞。例如,QNX 在这种情况下也会调用失败。)您显然正在运行一个操作系统(在没有考虑根目录和挂载点的情况下,您的问题不涉及这些因素)选择另一个允许的替代方案,即取消链接目录,删除...条目,并禁止创建新条目。

进一步阅读

  • “rmdir”开放群组基础规范. IEEE 标准 1003.1。第 7 期。2013 年。
  • “rmdir”QNX Neutrino 实时操作系统库参考。 QNX 开发人员支持。

答案2

作为 JdeBP 优秀产品的补充回答,你可以通过检查相关目录的 inode 来确认确实发生了这种情况:

$ mkdir ~/foo
$ ls -di ~/foo
16654483 /home/terdon/foo
$ cd ~/foo
$ rmdir ../foo/
$ ls -di ../foo
ls: cannot access ../foo: No such file or directory
$ mkdir ../foo
$ ls -di ../foo
16654484 ../foo

请注意,inode 编号已更改,这是一个新目录,除了恰好具有相同的名称之外,与旧目录没有任何关联。

相关内容