I understand why hard links on directories are dangerous (loops, problems for rmdir because of the parent-directory-link) and have read the other questions on that topic. And so I assumed that hard links on directories apart from . and .. are not used. And yet I see the following on CentOS 5 & 6:

# ls -id /etc/init.d/
459259 /etc/init.d/
# ls -id /etc/rc.d/init.d/
459259 /etc/rc.d/init.d/
# ls -id /etc/init.d/../
458798 /etc/init.d/../
# ls -id /etc/rc.d/
458798 /etc/rc.d/
# ls -id /etc/
425985 /etc/

In other words 2 different paths to directories pointing to the same inode and the parent of /etc/init.d/ pointing to /etc/rc.d/ instead of /etc/. Is this really a case of hard-linked directories? If not, what is it? If yes, why does Red Hat do that?

Edit: I'm sorry for asking a stupid question, I should have been able to see that it's a symlink. Not enough coffee today, it seems.

  • Directories cannot be hardlinked.
    – dr_
    Jul 27 '17 at 13:13
  • @user2845840 I wouldn't call it a stupid question at all. I'd stay you stumbled upon a less understood behavior of UNIX systems with respect to path and trailing slashes as I explained below.
    – penguin359
    Mar 21 '18 at 6:30

On RHEL, Fedora and CentOS, /etc/init.d is a symlink to /etc/rc.d/init.d. There is no hard link involved.

Even if Red Hat wanted to, it wouldn’t be possible on the file systems used.


That's soft-link, not hard link. Symbolic links point to other files. Opening a symbolic link will open the file that the link points to. Removing a symbolic link with rm will remove the symbolic link itself, but not the actual file.

This is indicated by the letter l at the beginning of the permissions

lrwxrwxrwx. 1 root root 11 Aug 10 2016 init.d -> rc.d/init.d

Also all the rc0.d to rc6.d are symlinks to rc.d/rc0.d


This post is a little old, but I don't feel like the behavior that the OP is seeing has yet been explained. As others have stated, /etc/init.d is a symbolic link to /etc/rc.d/init.d. The missing part is the reason that both paths used above return the same inode which is due to the use of the trailing forward-slash. When a path ends in a forward slash, it tells the kernel and other tools that a directory is intended. It can protect a mv/cp command from renaming a file when the intended destination was supposed to be a directory that doesn't actually exist. It also causes the lstat(2) system call used by ls to dereference the symbolic link and instead return the directory that it points to (or thrown an error if it doesn't point to an existing directory). Try this example to see the difference:

$ ls -id .
927578 .
$ ls -id ./parent
927641 ./parent
$ ls -id ./parent/
927641 ./parent/
$ ls -id ./parent/child
927643 ./parent/child
$ ls -id ./parent/child/
927643 ./parent/child/
$ ls -id ./child
927645 ./child
$ ls -id ./child/
927643 ./child/
$ ls -idL ./child
927643 ./child
$ ls -id ./child/..
927641 ./child/..
$ ls -id ./child/../..
927578 ./child/../..

You can see that the presence of the trailing slash only matters for the symbolic link case, but does hide the inode of the link. Also, the -L option to ls does something similar, albeit for any file type.

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.