In the first terminal A, I create a directory, enter the directory, and create a file:
$ mkdir test
$ cd test
$ touch file1.txt
$ ls
file1.txt
Then in another terminal B, I delete the directory:
$ rm -r test
$ mkdir test
$ cd test
$ touch file2.txt
And back again the terminal A (not doing any cd
), I try to list the files:
$ ls
ls
doesn't see anything and it doesn't complain either.
What happens in the background? How comes that ls
doesn't see the problem? And is there a standard, portable, and/or recommended way to find out that something is not right in the terminal A?
pwd
just prints the seemingly correct directory name. touch file3.txt
says no such file or directory which is not helpful. Only bash -c "pwd"
gives a two long error lines which somehow give away that something is wrong but are not really descriptive and I'm not sure how portable that is between different systems (I'm on Ubuntu 16.04). cd .. && cd test
fixes the problem, but does not really explain what happened.
Best Answer
There is no "problem" in the first place.
There is nothing not right. There are defined semantics for processes having unlinked directories open just as there are defined semantics for processes having unlinked files open. Both are normal things.
There are defined semantics for unlinking a directory entry that referenced something (whilst having that something open somewhere) and then creating a directory entry by the original name linking to something else: You now have two of those somethings, and referencing the open description for the first does not access the second, or vice versa. This is as true of directories as it is of files.
A process can have an open file description for a directory by dint of:
opendir()
library function; oropen()
library function.rmdir()
is allowed to fail to remove links to a still-open directory (which was the behaviour of some old Unices and is the behaviour of some non-Unix-non-Linux POSIX-conformant systems), and is required to fail if the still-open directory is unlinked via a name that ends in a pathname component.
; but if it succeeds and removes the final link to the directory the defined semantics are that a still-open but unlinked directory:Your operating system is one of the ones that does not return
EBUSY
fromrmdir()
in these circumstances, and your shell in the first terminal session has an unlinked but still open directory as its current directory. Everything that you saw was the defined behaviour in that circumstance.ls
, for example, showed the empty still open first directory, of the two directories that you had at that point.Even the output of
pwd
was. When run as a built-in command in that shell it was that shell internally keeping track of the name of the current directory in a shell/environment variable. When run as a built-in command in another shell, it was the other shell failing to match the device and i-node number of its working directory to the second directory now named by the contents of thePWD
environment variable that it inherited, thus deciding not to trust the contents ofPWD
, and then failing in thegetcwd()
library function because the working directory does not have any names any longer, it having been unlinked.Further reading
rmdir()
. "System Interfaces". The Open Group Base Specifications. IEEE 1003.1:2017.