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.

7
  • 1
    Try rm -r 'pwd' to remove the current dir without actually moving to parent dir
    – faadi
    Jun 13, 2016 at 6: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, 2016 at 6:45
  • 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, 2016 at 8:57
  • 7
    Imagine doing rm -rf .* only to find this including not only . but also .., and then ../.., and then…
    – gerrit
    Jun 13, 2016 at 9:42
  • 3
    Relevant: Does 'rm .*' ever delete the parent directory?
    – terdon
    Jun 13, 2016 at 11:04

2 Answers 2

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.

5
  • 9
    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, 2016 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, 2016 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. Jun 13, 2016 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 unix.stackexchange.com/questions/22394/…
    – jlliagre
    Jun 13, 2016 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, 2016 at 0: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.

11
  • 13
    But why/how does the hypothetical rmdir . command compromise file system integrity in a way that rmdir $(pwd) or rmdir "$PWD" does not? Jun 13, 2016 at 7: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. Jun 13, 2016 at 7:18
  • 7
    I'm afraid it looks conjectural.
    – Emmanuel
    Jun 13, 2016 at 8:09
  • 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, 2016 at 13:18
  • 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, 2016 at 5:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.