How to change a symbolic link to a directory to another target?
# ln -sv /path/to/target /path/to/link
‘/path/to/link’ -> ‘/path/to/target’
Now I want to replace that target with target2:
# ln -sfv /path/to/target2 /path/to/link
‘/path/to/link/target2’ -> ‘/path/to/target2’
Whoa! What happened there? Trailing slashes have no effect whatsoever:
ln -sfv /path/to/target2/ /path/to/link
‘/path/to/link/target2’ -> ‘/path/to/target2/’
# ln -sfv /path/to/target2/ /path/to/link/
‘/path/to/link/target2’ -> ‘/path/to/target2/’
# ln -sfv /path/to/target2 /path/to/link/
‘/path/to/link/target2’ -> ‘/path/to/target2’
How to achieve ’/path/to/link’ -> ’/path/to/target2’
?
Solution 1:
Use -n
/--no-dereference
("treat LINK_NAME as a normal file if it is a symbolic link to a directory"):
$ ln -sv /var/log /tmp/my-link
‘/tmp/my-link’ -> ‘/var/log’
$ ln -sfnv /var/opt /tmp/my-link
‘/tmp/my-link’ -> ‘/var/opt’
That is, ln -s target link
will work like ln -s target link/target
if link
links to a directory.
Most Linux command tools will try to dereference symbolic links before applying their action, otherwise symbolic links would be mostly just confusing and almost useless. I guess the original ln
authors thought consistency was more important than a certain amount of simplicity (with the risk of being confusing to people used to other tools) in this case.
Solution 2:
l0b0's answer is a good one. It's simple, and that makes it the best for command line use most of the time. In some cases though, you might care that it's not atomic. ln -sf
first deletes the old symlink, then creates the new one, so there's a brief period where no symlink exists.
If there's a need to be careful, you are better off to create the new symlink in a temporary location, and then mv
it into place.
There's a ruby implementation of that here: http://blog.moertel.com/posts/2005-08-22-how-to-change-symlinks-atomically.html. It'd be easy to implement in any language though. Beats me why it's not the default behaviour of ln.