7
$ mv . ../general/
mv: cannot move `.' to `../general/.': Device or resource busy

Does it mean that the current directory is a busy device or resource, and can't be moved away? Why is it?

4 Answers 4

8

You can't move the directory you're current in. The current process is the one that's keeping it busy.

Instead, go up one level and name the previously-current directory to move it to the target.

8

It is not possible to move a dot .. The dot is not the same as current directory name. You can think about . as a pointer to the directory, but not the directory itself, therefore,

$ pwd && echo $PWD && realpath .
/home/jimmij/tmp
/home/jimmij/tmp
/home/jimmij/tmp
$ mkdir tmp1 tmp2
$ mv tmp1/. tmp2/
mv: cannot move ‘tmp1/.’ to ‘tmp2/.’: Device or resource busy

doesn't work, but

cd tmp1
mv ../tmp1 ../tmp2

works fine, so actually you can move current directory, although some commands can be confused after this operation:

$ pwd && echo $PWD && realpath .
/home/jimmij/tmp/tmp1
/home/jimmij/tmp/tmp1
/home/jimmij/tmp/tmp2/tmp1
$ cd .
$ pwd && echo $PWD && realpath .
/home/jimmij/tmp/tmp2/tmp1
/home/jimmij/tmp/tmp2/tmp1
/home/jimmij/tmp/tmp2/tmp1

Similar story with .., i.e. parent directory.

In other words each directory must contain at least two elements: . and ... You cannot move or delete them.

5

The reason you're getting the message:

mv: cannot move .' to../general/.': Device or resource busy

is due to how the ., and .. work in addition to mv. When you move something in Unix, the mv command attempts to unlink everything that references the inode of the item that you're attempting to move. In this case that would be the inode of whatever the directory is that . is referencing.

The "symbols/links" . and .. are linking to inodes and are in a sense special. You can read about their history here in the U&L Q&A titled: Why does a new directory have a hard link count of 2 before anything is added to it? If you've ever looked at a newly created directory, you'll notice that it always starts with a linked count of 2. The reason is due to the existence of the . and ...

$ mkdir adir

$ ls -l | grep adir
drwxrwxr-x. 2 saml saml 4096 Oct  5 08:02 adir

$ ls -la adir/
total 8
drwxrwxr-x. 2 saml saml 4096 Oct  5 08:02 .
drwxrwxr-x. 3 saml saml 4096 Oct  5 08:02 ..

NOTE: Reference for ls output if you're unclear is here in this U&L Q&A titled: What do the fields in ls -al output mean?

So they aren't names of actual directories, but are "symbols/links" that are linking to them. Therefore they meed to be unlinked prior to being able to mv.

Well since your command is using the ., it cannot be unlinked by the mv command, hence the msg: "Device or resource busy".

References

3

Linux forbids renaming any path that ends in the component . or .., returning the error EBUSY; the following will also fail:

$ mkdir a a/aa
$ mv a/aa/.. b
mv: cannot move ‘a/aa/..’ to ‘b/..’: Device or resource busy

The code for this is in namei.c::renameat. The last component of the pathname when passed to various functions needs to be of type LAST_NORM, not LAST_DOT or LAST_DOTDOT.

FreeBSD returns the error EINVAL in each of these cases.


We can only guess as to why there is this restriction.

The rename() function shall fail if:
...
[EBUSY] The directory named by old or new is currently in use by the system or another process, and the implementation considers this an error.

One could consider . to currently be in use by the process. But note that Linux allows the following, so a directory merely being in use by some process is not sufficient for rename to fail:

$ mkdir /tmp/t
$ cd /tmp/t
$ mv /tmp/t /tmp/t1
$ /bin/pwd
/tmp/t1

The reason for forbidding the renaming of . and .. is probably "leads to less user confusion".

  • . is typically a hard link to the directory's entry in its parent, and is somewhat special in that a process can always open . to access its current working directory. Being able to rename it would be counterproductive.
  • .. is typically a hard link to the directory's parent, and is somewhat special in that a process opening .. will get the parent directory (or the directory itself, if it's a mount point). Being able to rename it would be counterproductive.

Linux also forbids rmdir of a path whose last component is .. (ENOTEMPTY) or . (EINVAL). FreeBSD returns the error EINVAL for each of these. The POSIX standard for rmdir has this:

The rmdir() function shall fail if:
...
[EINVAL] The path argument contains a last component that is dot.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .