8

I'm refreshing my understanding of a few basic GNU/Linux commands that I admit that I never really understood fully for the last 20+ years.

$ man ln in part says:

-n, --no-dereference
          treat LINK_NAME as a normal file if it is a symbolic link to a directory

To try to understand this better, I broke this down as follows:

$ mkdir dir1
$ ln -vs dir1 dir2
'dir2' -> 'dir1'
$ mkdir dir3; touch dir3/xx

$ tree -F .
├── dir1/
├── dir2 -> dir1/
└── dir3/
└── xx

Now to test -n, first as a hard link

$ ln -vn dir3/xx dir2 ln: failed to create hard link 'dir2': File exists

and second as a symbolic link

$ ln -vsn dir3/xx dir2 ln: failed to create symbolic link 'dir2': File exists

??? why do these both fail ???


Only the first command form in the SYNOPSIS calls out a 'LINK_NAME', in this syntax:

   ln [OPTION]... [-T] TARGET LINK_NAME

So this says that the -n and --no-dereference options ONLY relate to the first command form for ln, (and not the other three command forms).

In my example:

The TARGET is dir3/xx, and
the LINK_NAME is dir2 ('a symbolic link to a directory').

The manual says that if LINK_NAME (i.e. remember this is the name of the link we are supposedly creating) is 'a symbolic link to a directory'...

... then we are supposed to treat this symbolic link as a 'normal file'.

What am I missing?

Elliptical view
  • 3,921
  • 4
  • 27
  • 46
  • I see. By default, the behavior is that if LINK_NAME is a directory it is first dereferenced. And if it is a directory, then it becomes 'the' DIRECTORY to create the link in, rather than the name of the link, as probably was intended. In that case the link name is created from the target's base name. -n stops this non-sense and issues an error message that LINK_NAME already exists. .. That is unless -f is used, in which case -n is ignored. – Elliptical view Jan 09 '20 at 22:13

1 Answers1

13

Without -n, both your ln commands would create links inside dir2: if LINK_NAME exists and is a directory or a symlink to a directory, the link is created inside the directory (if possible).

That’s what -n changes here: ln won’t consider LINK_NAME as a directory (if it’s a symlink). Since LINK_NAME already exists, ln fails. Adding -f will cause the existing symlink to be replaced:

ln -nsf dir3 dir2

will replace dir2 instead of creating a link inside dir2.

Stephen Kitt
  • 434,908