Is symlink's target relative to the destination's parent directory and if so, why?
Clash Royale CLAN TAG#URR8PPP
up vote
11
down vote
favorite
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...
symlink
add a comment |Â
up vote
11
down vote
favorite
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...
symlink
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 a comment |Â
up vote
11
down vote
favorite
up vote
11
down vote
favorite
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...
symlink
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...
symlink
symlink
edited Dec 18 '13 at 13:40
asked Dec 17 '13 at 21:34
jibsales
17517
17517
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 a comment |Â
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
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
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
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 a comment |Â
2 Answers
2
active
oldest
votes
up vote
11
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. They 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.
add a comment |Â
up vote
5
down vote
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 nonsensical, let alone impossible.
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.
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
11
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. They 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.
add a comment |Â
up vote
11
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. They 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.
add a comment |Â
up vote
11
down vote
accepted
up vote
11
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. They 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.
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. They 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.
edited Nov 25 '14 at 12:49
answered Dec 17 '13 at 22:19
sparticvs
1,909918
1,909918
add a comment |Â
add a comment |Â
up vote
5
down vote
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 nonsensical, let alone impossible.
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.
add a comment |Â
up vote
5
down vote
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 nonsensical, let alone impossible.
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.
add a comment |Â
up vote
5
down vote
up vote
5
down vote
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 nonsensical, let alone impossible.
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.
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 nonsensical, let alone impossible.
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.
edited 12 mins ago
Communityâ¦
1
1
answered Dec 17 '13 at 22:16
Joseph R.
27.6k370113
27.6k370113
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f105637%2fis-symlinks-target-relative-to-the-destinations-parent-directory-and-if-so-wh%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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