11

I'm trying to emulate the process of path resolution (see man page path_resolution) in unix-like systems.

My OS is Linux with GNU coreutils 8.7.

In order to clarify the meaning of extra trailing '/' in resolution, I did following things in a shell:

mkdir this_is_dir
ln -s this_is_dir this_is_link
rm this_is_link

Everything was fine, because this_is_link is a symlink, and I just removed it away. But while trying:

mkdir this_is_dir
ln -s this_is_dir this_is_link
rm this_is_link/

It echoed rm: cannot remove 'this_is_link/': Is a directory

Well, the trailing '/' caused following of symlink, I thought. So, I tried another command: rmdir this_is_link/

And a funny result came out: rmdir: failed to remove 'this_is_link/': Not a directory

Not what I expected. So I asked my friend to confirm if the same result could be obtained on his system. He had a lower version of coreutils than I had. And the result was amazing, no matter rm or rmdir 'this_is_link/', the same error Not a directory occurs.

And another friend just tried it out on his Mac OS, the result is: rm => 'Is a directory', rmdir => the directory is successfully deleted, the link remained.

Are there any spec about the exact behavior of path resolution?

1

2 Answers 2

11

The POSIX/Single Unix specification specifies that a pathname with a trailing slash must refer to a directory (see base definitions §4.11 pathname resolution). foo/ is in fact defined as equivalent to foo/. (for path resolution purposes, not when manipulating file names; basename and dirname ignore trailing slashes). Most implementations respect this, but there are a few exceptions.

This explains the behavior of rm this_is_link/: it's equivalent to rm this_is_link/., where the argument is clearly a directory.

rmdir this_is_link/ should similarly refer to the directory. That it doesn't on your machine is a bug in GNU coreutils. OSX is behaving correctly here.

5
  • This is exactly what i needed, thanks guy!
    – ymfoi
    Jan 24, 2012 at 3:10
  • if path/ was equivalent to path/., then rmdir would have to fail too, because the rmdir utility is supposed to "perform actions equivalent to the rmdir() function", and the rmdir() function should fail with EINVAL when "The path argument contains a last component that is dot". (The quotes are from the POSIX). Or that should not apply when the trailing /. is, like, imaginary? That may be. Anyways, the behaviour of the rmdir utility from GNU coreutils correctly reflects that of the rmdir() function of the system it runs on, and this answer is wrong.
    – user313992
    Jan 23, 2021 at 11:28
  • @user414777 IIRC what you explain was reported as a defect on the POSIX specification and the semantics of a trailing slash have been modified to make this case work "intuitively". Jan 23, 2021 at 17:25
  • 1
    Even if that's a bug in Linux, it's still not bug in GNU coreutils, as you claim. GNU's rmdir will work as you expected on OSX.
    – user313992
    Jan 24, 2021 at 13:11
  • 1
    Coreutils > 8.32 will have more helpful error messages in this regard: lists.gnu.org/archive/html/coreutils/2021-02/msg00009.html Specifically rmdir: failed to remove 'this_is_link/': Symbolic link not followed Feb 17, 2021 at 16:44
-1

My take:

  • ''rm link/'' fails because rm looks at the last char, sees it's a slash, gives the (not really correct) diagnostic you saw;
  • ''rmdir link/'' fails alright: link is not a directory, it is a symlink
  • ''rm link'' will correctly succeed

Incidentally, path resolution has very little to do with this, it just appears to be ''rm'' cutting a corner rather than (correctly) invoking "stat" on an argument (which is what rmdir is doing).

Cheers.

8
  • 1
    Actually, the converse seems to be true: rm does call stat (well, newfstatat, actually, with the AT_SYMLINK_NOFOLLOW option) and refuses to proceed any further, whereas rmdir actually calls rmdir(2), but gets ENOTDIR. Jan 23, 2012 at 10:47
  • @AnsgarEsztermann AT_SYMLINK_NOFOLLOW will prevent it from following the symlink, so rm should delete the link itself instead of printing "Not a directory" which does not match the circumstance.
    – ymfoi
    Jan 23, 2012 at 11:06
  • From a brief check with stat(1), the trailing slash will override the option. The output of stat and stat -L differ only if the argument is given without a trailing slash. Jan 23, 2012 at 13:21
  • @AnsgarEsztermann Oh, I see...Thx. How about the different effects on different evironment? Any ideas?
    – ymfoi
    Jan 23, 2012 at 14:08
  • 1
    It's the opposite: on ymfoi's machine, rm is behaving correctly and rmdir isn't. The trailing / should force them to treat their argument as a directory, per the POSIX standard. See my answer for references. Jan 24, 2012 at 0:56

You must log in to answer this question.

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