63

I need a symlink that resolves relative to the directory it is placed in. What command is used to create such a thing?

78
  1. Go to the directory you want the link to reside in
  2. Run the command ln -s ../some/other/file linkname

The path you provide is stored with the file. When you access the file the stored path is looked up and expanded relative to the file. It does not know what directory you were in when you created the link.

  • 23
    No you don't. You just have to make sure that you specify the location relative to the link name instead of your current directory. – Ignacio Vazquez-Abrams May 28 '10 at 8:26
  • 5
    To help in understanding: The path you provide is stored with the file. When you access the file the stored path is looked up and expanded relative to the file. It does not know what directory you were in when you created the link. – Marian May 30 '10 at 14:27
  • 2
    exactly equivalent: ln -s ../some/other/file /some/dir/linkname – sehe Dec 22 '11 at 12:07
  • 1
    Instead of going down a directory and the up again, you can also just do ln -s ./file linkname since . refers to the current directory. – pduersteler Mar 12 '13 at 13:36
  • 1
    ln -s somedir/original-dir link-name does not work. It creates a directory with name link-name that contains an invalid link. The command that works is ln -sr somedir/original-dir link-name – Lorenz Meyer May 18 '16 at 9:09
29

Recent versions of GNU coreutils' ln (>= 8.16) support the --relative (or -r) option which means you can call ln -s with 2 absolute or relative (in respect to your working directory) paths and it will figure out the correct relative path that has to be written to the symlink.

  • 2
    Thanks. The -r option is helpful when you are cross-compiling and need absolute paths on the build host but relative paths on the target. – Robert Calhoun Sep 1 '15 at 15:57
  • rdfind can produce some really bad symlinks that are not only absolute, but backtrack off of directories for no reason. ln -r -s targetfile myalias can help you fix it – Ray Foss Mar 13 at 15:47
2

What you need to understand is basically that a symlink is more like a text file than like a directory entry which contains a file. So if you

echo ../poo >/file/name

then that is quite similar to

ln -s ../poo /file/name

The system doesn't care if /file/../poo exists at all, it's just a piece of text which gets put into the symlink. When something tries to open the symlink, that's when the system tries to resolve it.

If you are using a shell with file name completion, this feature can confuse things by allowing you to complete a file name relative to your current working directory, even if you then end up using that as the target of a symlink in completely another directory.

  • This is abused by some system calls -- I know e.g. BSD used to allow you to symlink a particular system file to < to change how the system allocated memory. Of course there is no file named < in that directory, it's just a cheap way of creating a very small file-like thing which has some attractive properties over a regular text file on that particular platform. – tripleee Apr 25 '18 at 7:27
  • That link is now dead. Try man.openbsd.org/OpenBSD-5.3/man5/malloc.conf.5 but notice also that the behavior in more recent versions of OpenBSD is a lot less ... colorful. – tripleee Mar 7 at 15:14
0

Relative links were tricky for me on OS X, i.e.

~/Dropbox/git/dave-bot $ ln -s ../codyhess/bin ~/bin
~/Dropbox/git/dave-bot $ ln -s ../codyhess/bin/ ~/bin

both did not work (something was created but it wasn't a directory). I created the desired link by using absolute paths.

~/Dropbox/git/dave-bot $ ln -s ~/Dropbox/git/codyhess/bin/ ~/bin
  • It's a viable solution, so doesn't need to be a comment. This can stay as a separate answer. – slhck Oct 5 '11 at 20:43
  • 1
    Your initial try with relative links is just plain wrong and that's why it's not working. You've misunderstood how relative links work. There's nothing particularly tricky about it (not even if you are using OS X). Perhaps you got misguided by the other answers talking about chancing your working directory when you create the link. That was just to make it easier to do the link correctly and is in no way necessary. You do not define the relative path relative to your current dir, but to the directory of the link. This is what you were after: ln -s Dropbox/git/codyhess/bin ~/bin – Timo May 8 '16 at 17:29
  • Also @slhck when someone is asking specifically how to create relative links in what world does a saying that you can do absolute links constitutes a "viable solution"? It specifically does not answer the OPs question and hence is quite the opposite of solution, it's no solution. This shouldn't be a comment nor an answer, it should be a question "How exactly do relative links work (explained so that mac users understand it)?". I hope this mac user now explained it well enough. :) – Timo May 8 '16 at 17:33
  • @TimoLehto Perhaps you want to address the comment to the original author (Cody Hess). I only copyedited the post. – slhck May 10 '16 at 11:22
  • @slhck, I directed it to you, because you deemed the solution as "viable" and your comment made me think that you would be the person to convince if one wanted to flag the answer as a "not an answer" (and get the flagging accepted). – Timo May 11 '16 at 8:22
0

I just wanted to further explain how to create a symlink using relative paths (with a detailed example).

As Ignacio Vazquez-Abrams mentioned in the comments, you must specify the file/folder location relative to where the symlink will be created, not relative to your current directory.

EXAMPLE

You are in /usr/share/nginx/html/_src/learn You will create a symlink coding in /usr/share/nginx/html

Create relative symlink(theory):

sudo ln -s /path/to/source/file-or-folder/relative/from/symlink /path/to/symlink/relative/to/current/location

Create actual relative symlink:

sudo ln -s ./_src/learn/coding ../../coding

More information (same example)

current path:                                  /usr/share/nginx/html/_src/learn
symlink(to be) relative to current path:       ../../coding                 
symlink location (absolute):                   /usr/share/nginx/html/coding
folder/file relative to symlink location:      ./_src/learn/coding
folder/file absolute path:                     /usr/share/nginx/html/_src/learn/coding  

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.