Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I've got the following file structure:

build/
client/
  –> index.js

And when I try to create a symbolic link named "client" inside the build directory that refers to the client directory in the cwd like so

// Fails
$ pwd
/home/user/
$ ln -s client build/client 
$ stat build/client/index.js
stat: build/client/index.js: stat: Too many levels of symbolic links

I get the ELOOP error displayed above. When I change the target path to be relative to the destination path, all is good:

// Works
$ pwd
/home/user/
$ ln -s ../client build/client 
$ stat build/client/index.js
stat: <outputs file stats>

Is this the intended behavior and please explain why...

share|improve this question
    
this has probably something to do with th efact that using ../ use absolute path to declare path instead of relative path. a good pratice is to always use absolute path –  Kiwy Dec 17 '13 at 22:11
    
I agree with the best practice as I've always used absolute paths for both the target and the destination. However, the man pages state that relative paths can be used for both... –  jibsales Dec 17 '13 at 22:13
add comment

2 Answers

up vote 5 down vote accepted

For the one that doesn't work, if we look at the ls -l result, we get the following:

[sparticvs@sparta test]$ ls -l build/
total 0
lrwxrwxrwx. 1 sparticvs sparticvs 6 Dec 17 16:08 client -> client

Now to understand what is going on here. Let's look at the command you called:

ln -s client build/client

According to the Man Page, there are two possible matches for this format

SYNOPSIS
       ln [OPTION]... [-T] TARGET LINK_NAME   (1st form)
       ln [OPTION]... TARGET... DIRECTORY     (3rd form)

It will match on the first form (since its first). Now, the "target name" or client in your case, can be (according to the complete ln manual) arbitrary strings. The don't have to resolve to anything right now, but can resolve to something in the future. What you are creating with your invocation is a "dangling symlink" and the system does not keep you from creating these.

Now your second invocation ln -s ../client build/client is what is called a "relative symlink" (as you noted in your own post). There is a second type and that is an "absolute symlink" which would be called by doing ln -s /home/user/client build/client.

This is not a bug. According to the manual it states:

When creating a relative symlink in a different location than the current directory, the resolution of the symlink will be different than the resolution of the same string from the current directory. Therefore, many users prefer to first change directories to the location where the relative symlink will be created, so that tab-completion or other file resolution will find the same target as what will be placed in the symlink.

-- from info coreutils 'ln invocation'

That said, you MUST use either the relative or absolute path to the target.

share|improve this answer
add comment

This is indeed the intended behavior. From the ln(1) man page:

Symbolic links can hold arbitrary text; if later resolved, a relative link is interpreted in relation to its parent directory.

As to the why of it, imagine if the symlink were instead interpreted relative to its source rather than its destination. When later resolving it, you would need to know what your CWD was when you created it, which is impossible, let alone nonsensical.

Moreover, this way you get a neat and compact method to create a skeleton directory structure that you can drop anywhere in the directory tree without breaking the symlinks.

To give you an example of what I mean, let's say you're working on a project and you have a whole directory structure set up for it like so:

$ ls -1 /home/you/project
thingummies/
widgets/
wizardry/

Now suppose you wanted to create a symlink to widgets/ inside wizardry/. You have two options:

$ ln -s /home/you/project/widgets /home/you/project/wizardry

or

$ ln -s ../widgets /home/you/project/wizardry

If you then try moving /home/you/project anywhere else, a symlink created with the first form will break because it's looking for /home/you/project/widgets. The second form will keep the symlink functional because it's looking for ../widgets relative to the place it's in, regardless of where that place might be in the directory tree.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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