Command: > mkdir -p .x > ln -sfF /bin/ls .x/ fails: > ln: .x/: No such file or directory The expected result is to create a symlink .x/ls -> /bin/ls
There is no bug on ln(1)'s part. The -F option checks if your last argument is a directory and if it is, it removes it only if it's empty (see code below). static int Fflag; /* Remove empty directories also. */ if (Fflag && S_ISDIR(sb.st_mode)) { if (rmdir(target)) { warn("%s", target); return (1); } } The reason your command fails doesn't have to do with the -F option - it has to do with the fact that you're trying to create a link named `.x/`, and as you probably know, you're not allowed to use slashes inside a name, so symlink(2) fails. You'd get the same error no matter what option you used. If you want your command to work, simply write it as `ln -sfF /bin/ls .x`.
> The -F option checks if your last argument is a directory and if it is, it removes it only if it's empty (see code below). But this isn't what ln(1) says: > -F If the target file already exists and is a directory, then remove > it so that the link may occur. The target of the link in this case is a file .x/ls and it doesn't exist.
There is an ambiguity here: target_file vs. target of the link. When the user specifies "-F" he means "target of the link" (the object being created). IMO a correct fix here is to fix ln(1) to apply "-F" to the "target of the link", and to correct the manpage accordingly.
> The target of the link in this case is a file .x/ls and it doesn't exist. It seems that the -F option interprets `.x/` literally, so it tries to create a file named `.x/` which obviously doesn't work. You'd have to write the command as `ln -sfF /bin/ls .x/ls` in order for it work the way you want it to. > When the user specifies "-F" he means "target of the link" (the object > being created). IMO a correct fix here is to fix ln(1) to apply "-F" to > the "target of the link", and to correct the manpage accordingly. I think the reason behind the fact that -F doesn't "fill in" the target's name (i.e `.x/` to `.x/ls`) is to prevent commands such as `ln -sfF foo .` which would mean that the current working directory has to be deleted if it's empty. It makes sense that -F doesn't have the same behavior as the other options since it involves deleting stuff and the command I mentioned above is a common command and very easy way to mess things up, especially if -F is used inside a script.
> [...] to prevent commands such as `ln -sfF foo .` which would mean that the current working directory has to be deleted if it's empty ln(1) can make exceptions for corner cases like this.