macosshellfilesystemsposixapfs

unexpected behavior of directory renaming in macos (other posix flavors?)


Basically, in Python or bash I can rename a directory to a different name from within that directory : at that point, from within the directory, the old name still shows, but the rename has in fact already taken place.

On macos with APFS, this came about in a Python script I was writing to rename directories as per a specific naming convention I use and I noticed this behavior.

I am posting this as posix/shell/macos as I half expect this to happen as well under Linux and I got the same general behavior out of the zshell.

Let's say I have a directory, foo:

(venv) jluc@test$ tree
.
└── foo

I rename it to bar with mv foo bar

(venv) jluc@test$ tree
.
└── bar

But now, let's cd into that directory and perform the rename there.

$cd bar
$pwd
/Users/jluc/kds2/wk/explore/test/bar
$ mv ../bar ../zoom
$ pwd
/Users/jluc/kds2/wk/explore/test/bar  👈 still the old name

So, now, within bar, I've renamed it to zoom. It did not error out. Locally, a pwd shows that I am still in the same directory. I can do an ls and I am not in a invalid directory which some commands can sometime put me in.

However, a tree one level up tells a different story.

(venv) jluc@bar$ tree ..
..
└── zoom  👈 but here I see the new name

and cd to the current directory fails

cd `pwd`
-bash: cd: /Users/jluc/kds2/wk/explore/test/bar: No such file or directory

What, in the name of Schrodinger's 😺, is going on? Does the inode scheme underlying the file system, APFS, provide this? Would different filesystems, like ext4 for example also exhibit the same behavior?

Update: if I have a separate text file in my testing directory, I can cat the contents of the file before and after the rename locally, so it's not just the shell - the file system collaborates as well. The current directory is still valid and operational (which would fit with @that other guy's answer).


Solution

  • There are two things at play:

    1. On Unix, any handle to an open file or directory will generally be unaffected by renames and deletions.
    2. The shell remembers the directory you're in, it doesn't re-query every time.

    #1 means that for the most part, you can delete or move a file/dir that's still in use, and the using process can continue using it until it's done. #2 means that the shell's pwd will just return the old name (though external /bin/pwd which has to requery will fail).