It appears as if the GNU ln
implementation on Linux uses the stat()
function to determine whether the target exists or not. This function is required to resolve symbolic links, so when the target of the pre-existing link is not accessible, the function returns EACCESS
("permission denied") and the utility fails. This has been verified with strace
to be true on a Ubuntu Linux system.
To make the GNU ln
use lstat()
instead, which does not resolve symbolic links, you should call it with its (non-standard) -n
option (GNU additionally uses --no-dereference
as an alias for -n
).
ln -s -n -f ../../../raw_data/CHIP_TEST/BM50.2.fastq 50ATC_Rep2.fastq
Reading the POSIX specification for ln
, I can't really make out whether GNU ln
does this for some undefined or unspecified behaviour in the specification or not, but it is possible that it uses the fact that...
If the destination path exists and was created by a previous step, it is unspecified whether ln
shall write a diagnostic message to standard error, do nothing more with the current source_file, and go on to any remaining source_files; or will continue processing the current source_file.
The "unspecified" bit here may give GNU ln
the license to behave as it does, at least if we allow ourselves to interpret "a previous step" as "the destination path is a symbolic link".
The GNU documentation for the -n
option is mostly concerned about the case when the target is a symbolic link to a directory:
'-n'
'--no-dereference'
Do not treat the last operand specially when it is a symbolic link
to a directory. Instead, treat it as if it were a normal file.
When the destination is an actual directory (not a symlink to one),
there is no ambiguity. The link is created in that directory. But
when the specified destination is a symlink to a directory, there
are two ways to treat the user's request. 'ln' can treat the
destination just as it would a normal directory and create the link
in it. On the other hand, the destination can be viewed as a
non-directory--as the symlink itself. In that case, 'ln' must
delete or backup that symlink before creating the new link. The
default is to treat a destination that is a symlink to a directory
just like a directory.
This option is weaker than the '--no-target-directory' ('-T')
option, so it has no effect if both options are given.
The default behaviour of GNU ln
when the target is a symbolic link to a directory, is to put the new symbolic link inside that directory (i.e., it dereferences the link to the directory). When the target of the pre-existing link is not accessible, it chooses to emit a diagnostic message and fail (allowed by the standard text).
OpenBSD ln
(and presumably ln
on other BSD systems), on the other hand, will behave like GNU ln
when the target is a symbolic link to an accessible directory, but will unlink and recreate the symbolic link as requested if the target of the pre-existing link is not accessible. I.e., it chooses to continue with the operation (allowed by the standard text).
Also, GNU ln
on OpenBSD behaves like OpenBSD's native ln
, which is mildly interesting.
Removing the pre-existing symbolic link with rm
is not an issue whatsoever, as you appear to have write and executable permissions for the directory it's located in.