41

I tried removing the '.' directory. I thought I could just delete my working directory without having to go into a parent directory.

The point of my question is to look for some insight into how the linux system works to delete files.

Braiam
  • 35,991
JobHunter69
  • 940
  • 5
  • 12
  • 22
  • 1
    Try rm -r 'pwd' to remove the current dir without actually moving to parent dir – faadi Jun 13 '16 at 06:17
  • 7
    This question does not duplicate that one. That one asks why the hard link exists as a physical entity, rather than being synthesized. This question asks not only why rm . and rmdir . do not work, but why they are specified as not working, which is independent of the physical existence of a hard link. – JdeBP Jun 13 '16 at 06:45
  • @ThomasDickey this isn't a duplicate of that one either, only slightly related. In the other question, the OP is not using dot as parameter and the command doesn't fail. – jlliagre Jun 13 '16 at 08:43
  • 9
    Image you've climbed up into a tree to cut off a branch. Which side of the cut do you sit on when you begin to saw? (That's the Linux file system in a nutshell.) – michael Jun 13 '16 at 08:57
  • 7
    Imagine doing rm -rf .* only to find this including not only . but also .., and then ../.., and then… – gerrit Jun 13 '16 at 09:42
  • 3
  • Even if it were allowed, rmdir . wouldn't remove the working directory, because the link to it in the parent would still exist. It would just remove the directory's link to itself. – Barmar Jun 15 '16 at 17:58

2 Answers2

90

Removing the current directory does not affect the file system integrity or its logical organization. Preventing . removal is done to follow the POSIX standard which states in the rmdir(2) manual page:

If the path argument refers to a path whose final component is either dot or dot-dot, rmdir() shall fail.

One rationale can be found in the rm manual page:

The rm utility is forbidden to remove the names dot and dot-dot in order to avoid the consequences of inadvertently doing something like:

rm -r .*

On the other hand, explicitly removing the current directory (i.e. by stating its full or relative path) is an allowed operation under Unix, at least since SVR3 as it was forbidden with Unix version 7 until SVR2. This is very similar to what happens when you remove a file that is actively being read or written to. Processes accessing the delete file continue their read and write operations just like if nothing happened. After you have removed a process current directory, this directory is no more accessible though its path but its inode stay present on the file system until the process dies or change its own directory.

Note that the process won't be able to use a path relative to its current directory to change its cwd (e.g. cd ..) because there is no more a .. entry in its current directory.

When someone type rmdir ., they likely expect the current directory entry to be removed but when a directory is removed (using its path), three directory entries are actually removed, ., .., and the directory itself.

Removing only . and not this directory's directory entry would create a non compliant directory but as already stated, it is forbidden by the standard.

As @Emmanuel rightly pointed out, there is a second reason why removing . is not allowed. There is at least one POSIX compliant OS (Mac OS X with HFS+) that, with strong restrictions, supports creating hardlinks to existing directories. In such case, there is no clear way from inside the directory to know which hardlink is the one expected to be removed.

jlliagre
  • 61,204
  • 9
    http://pubs.opengroup.org/onlinepubs/9699919799/functions/rmdir.html "The meaning of deleting pathname /dot is unclear, because the name of the file (directory) in the parent directory to be removed is not clear, particularly in the presence of multiple links to a directory" – Emmanuel Jun 13 '16 at 12:23
  • @Emmanuel Removing a directory that has more than two links (i.e. is not empty) is already forbidden by design (non empty directory). A directory with a link count of one is forbidden by the standard (at least with file systems where link counts have a meaning). – jlliagre Jun 13 '16 at 13:19
  • 3
    @jlliagre: It's not a question of a directory containing multiple links, but a directory having multiple links. Some filesystems and/or operating systems disallow this, but not all. – Jörg W Mittag Jun 13 '16 at 18:09
  • @JörgWMittag A directory containing multiple directories has multiple links by design, because all of its subdirectories .. link to it. This is the unique case of link count > 2 for the overwhelming majority of OSes and file systems so "some file systems and/or operating systems" is an understatement. The only non historical known exception is Mac OS X with HFS+ which add restrictions about who and what can be done though. Granted the POSIX comment is directed to this oddity. See http://unix.stackexchange.com/questions/22394/why-are-hard-links-to-directories-not-allowed-in-unix-linux – jlliagre Jun 13 '16 at 20:27
  • Hey, I've done rm -r .* before and it blew away everything under the parent directory recursively... That was more than a decade or two ago but it's nice to know rm no longer allows this. – antak Jun 14 '16 at 00:59
9

It's done like that for integrity since you are currently inside that directory and the . is only a self-reference.

You need to either go in its parent or call rmdir with its path, which can be done with:

rmdir `pwd`

If you often need that, you can set an alias to it like:

alias rmc='rmdir `pwd`'

.. which could be called as rmc alone to remove current directory.

  • 13
    But why/how does the hypothetical rmdir . command compromise file system integrity in a way that rmdir $(pwd) or rmdir "$PWD" does not? – G-Man Says 'Reinstate Monica' Jun 13 '16 at 07:08
  • 4
    It is not a matter of FS integrity but of logical organization. When you chose your current directory, you tell the shell to use this directory for your upcoming operations, but you can not remove something from itself. – Julie Pelletier Jun 13 '16 at 07:18
  • 7
    I'm afraid it looks conjectural. – Emmanuel Jun 13 '16 at 08:09
  • 1
    @Emmanuel: This has been decided decades ago and I'm sure they had many good reasons including the one I gave and jlliagre's explanation. It would have been possible to support it either way but it was an intentional decision not to. – Julie Pelletier Jun 13 '16 at 09:13
  • Down voting because: 1. It's a terrible idea to use rm * and similar variant (think shell history) 2. The question is about "why", not about "how". 3. The statement about integrity is false. – Franklin Piat Jun 13 '16 at 12:13
  • 4
    @FranklinPiat I didn't find your comment particularly useful: 1. Where did the OP use rm *, and what do you mean by shell history? 2. The answer addressed the why part, 3. Care to elaborate? – JBentley Jun 13 '16 at 13:18
  • 1
    @JBentley Ignoring the rm * since I don't know either where that came from, but by far most of this answer is about the why, the how is only a minor note. That by itself wouldn't necessary be a problem, but I agree with Franklin Piat that that little how part there is looks pretty clearly wrong, there is nothing in this answer that supports the idea that the rationale is anything other than what's in the official rationale, quoted in jlliagre's answer. – hvd Jun 13 '16 at 17:51
  • 1
    @JBentley: (1) I’m also puzzled by Franklin Piat’s reference to rm *.  I guess the remark about shell history is a caution that you might accidentally (re-)execute a command from history, in a different context, with disastrous results.  However, by this line of thinking, you should never use commands that are potentially harmful (or you should disable shell history).  … (Cont’d) – Scott - Слава Україні Jun 13 '16 at 17:55
  • (Cont’d) …  (2) I suspect that Franklin and I are on the same page.  The answer says, “It’s done like that for integrity ….”  When I challenged that, the answerer switched to “It is not a matter of FS integrity but of logical organization.” and then backpedaled even further to “It would have been possible to support it either way but it was an intentional decision not to.”  So I agree that this answer doesn’t really address the why. – Scott - Слава Україні Jun 13 '16 at 17:55
  • 2
    This has turned up being a really strange useless debate that I really don't care about. I gave a rational reason and a solution to the problem. The POSIX committee probably didn't write down every single justification they had, especially what seems so obvious as they probably expected it to be to others and didn't really care about it all either. They just defined the rules which as I commented could have been handled differently to accommodate the different perceptions. – Julie Pelletier Jun 13 '16 at 18:06
  • 4
    @G-Man if you do rmdir $(pwd), pwd figures out a logical name for the current directory, for instance /foo/bar/baz, and then rmdir, seeing that path, removes the baz entry from the /foo/bar directory, provided the conditions are met. This makes sense. The command rmdir ., on the other hand, is an instruction to remove the . entry from the current directory, which is neither allowed (it would violate the constraint that every directory has a . entry pointing to itself) nor useful (it wouldn't remove the link you wanted removed). – hobbs Jun 14 '16 at 05:02