13

I have two shells open. The first is in directory A. In the second, I remove directory A, and then recreate it. When I go back to the first shell, and type ls, the output is:

ls: cannot open directory .: Stale file handle

Why? I thought the first shell (the one that remained open inside a non-existent directory) would "freeze" while waiting for the next command, and wouldn't have "realized" that the directory was deleted and recreated. Does the shell hold a "deeper" reference to its current working directory other than the string $PWD?

  • 2
    A non- answer, but if you'd simply like your shell to fall back on its feet, you can run cd $PWD. – dhag May 14 '15 at 21:18
  • I would like to understand what's going on, I know it's easy to get the shell back :) – fonini May 14 '15 at 22:25
  • Is this directory on an NFS server? I think that's the only situation where you get stale file handles. – Barmar May 20 '15 at 19:04
  • The directory is local. When you do this in your system, the result is different? – fonini May 20 '15 at 22:27
17

A directory (like any file) is not defined by its name. Think of the name as the directory's address. When you move the directory, it's still the same directory, just like if you move to a different house, you're still the same person. If you remove a directory and create a new one by the same name, it's a new directory, just like someone who moves into the house where you used to live isn't you.

Each process has a working directory. The cd command in the shell changes the shell's current working directory. The pwd command prints the¹ path to the current working directory.

When you removed the directory A, what this did was to remove the entry for A in its parent directory. The directory A itself remained in the filesystem, but in a detached state, with no name. It was not deleted yet because it was in use by a process, namely the first shell. When you changed the directory in the first shell, the directory was finally deleted. The same thing happens when a file is deleted while a process still has it open: the file's directory entry is removed immediately, and the file itself is removed when it stops being in use.

Similarly, observe what happens when you move directories around.

mkdir one two
touch one/1 two/2
cd one
ls

In another shell:

mv one tmp
mv two one
mv tmp two

In the first shell:

ls

The file 1 is in the directory that was originally called one and is now called two. The file 2 is in the directory that was originally called two and is now called one.

¹ More precisely, a path, which may not be unique if symbolic links or other subtleties are involved.

| improve this answer | |
  • So the key point here is that a process holds the inode of its working directory, not just the path? – Nacht May 15 '15 at 5:36
  • 1
    @Nacht The process holds a descriptor, but the kernel does all the mapping (descriptor/file tables entries/inode). And indeed, internally, the kernel does not store paths (because the interesting stuff is in the inode, not the path). Besides, a "path" is merely one link to a file... there may be several :) – John WH Smith May 15 '15 at 7:00
  • oh right it holds a descriptor. so bash constantly holds an fd of the working directory? surely not all processes have fds of the working directory... i thought i remembered fds starting at value 3 after stdin/out/err – Nacht May 15 '15 at 16:20
  • 2
    @Nacht The current directory isn't a file descriptor, but it works a lot like one. The kernel maintains that for every process. On Linux, you can see it in /proc/<pid>/cwd, which works like /proc/<pid>/fd/<number>. It's CWD in the output of lsof. – Gilles 'SO- stop being evil' May 15 '15 at 16:29
  • it is possible to make automatic cd - && cd - in such case? – Vitaly Zdanevich Aug 29 '16 at 6:25
8

The new directory A is not the same as directory A. It can be checked with stat command before deleting old one and after creating new one and you will see different i-node numbers.
And I think this is related to how kernel works. It simply keeps track of the i-number of the current directory for each process. So as there are different i-numbers this will lead to different collisions.

| improve this answer | |
  • It should be noted that an inode is a structure, not a unique number. It can be uniquely identified, but it holds more information than its ID. This is what makes it more important than links. – John WH Smith May 15 '15 at 7:01
  • 1
    @JohnWHSmith I am going to delete this answer as Gilles one is better. – taliezin May 15 '15 at 7:06
  • 6
    That's no reason to delete yours! If you feel that way, you could just add a disclaimer to your answer explaining that you consider the other one better. – terdon May 15 '15 at 8:59
7

This is expected behavior. The new directory A isn't the same as the old directory A, it just happens to have the same name. So the first terminal's $PWD is still gone, it didn't magically reappear when you did the mkdir A.

| improve this answer | |
  • 2
    could you elaborate on 'new directory A isn't the same as the old directory A'. What aspects of the file/directory change? Does it have to do with the inode number? Sorry to ask, but i'm just learning about this. – rahul May 14 '15 at 20:01
  • 2
    @rahul Philosophically, what changes is its identity — a new directory has been created from nothing at the same location. At an implementation level, yes, all open files are identified by inode, and the old and new directories will have distinct inodes with different inode numbers. – hobbs May 15 '15 at 5:41
0

A directory, like a file, has an inode associated with it:

307 % mkdir A B C

308 % ls -i 11997708 A 11997709 B 11997710 C

An inode is a data structure that contains information about the directory or file. Every directory and file has one. Think of it as an address (an index number really).

If I am in A, inode number 11997708 and in another shell (or in the same shell as am going to do) delete directory A then recreate it and ls the inode:

309 % cd A

310 % rmdir ../A

311 % mkdir ../A

312 % ls -i ..

11997720 A 11997709 B 11997710 C

The i node is different, so if it try to create a file in the deleted directory A:

313 % touch this

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

because the directory I am in - is no longer associated with the inode 11997720 - so where I currently am no longer has a legitimate address/index - inode. Thus the error.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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