Make a symbolic link to a relative pathname

symlink

I can do this:

$ pwd
/home/beau
$ ln -s /home/beau/foo/bar.txt /home/beau/bar.txt
$ readlink -f bar.txt
/home/beau/foo/bar.txt

But I'd like to be able to do this:

$ pwd
/home/beau
$ cd foo
$ ln -s bar.txt /home/beau/bar.txt
$ readlink -f /home/beau/bar.txt
/home/beau/foo/bar.txt

Is this possible? Can I somehow resolve the relative pathname and pass it to ln?

Best Answer

If you create a symbolic link to a relative path, it will store it as a relative symbolic link, not absolute like your example shows. This is generally a good thing. Absolute symbolic links don't work when the filesystem is mounted elsewhere.

The reason your example doesn't work is that it's relative to the parent directory of the symbolic link and not where ln is run.

You can do:

$ pwd
/home/beau
$ ln -s foo/bar.txt bar.txt
$ readlink -f /home/beau/bar.txt
/home/beau/foo/bar.txt

Or for that matters:

$ cd foo
$ ln -s foo/bar.txt ../bar.txt

It's important to realise that the first argument after ln -s is stored as the target of the symlink. It can be any arbitrary string (with the only restrictions that it can't be empty and can't contain the NUL character), but at the time the symlink is being used and resolved, that string is understood as a relative path to the parent directory of the symlink (when it doesn't start with /).

Related Question