Is symlink's target relative to the destination's parent directory and if so, why?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
11
down vote

favorite
4












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














up vote
11
down vote

favorite
4












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












up vote
11
down vote

favorite
4









up vote
11
down vote

favorite
4






4





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















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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
















  • 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










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.






share|improve this answer





























    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.






    share|improve this answer






















      Your Answer








      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "106"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













       

      draft saved


      draft discarded


















      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






























      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.






      share|improve this answer


























        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.






        share|improve this answer
























          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.






          share|improve this answer














          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.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 25 '14 at 12:49

























          answered Dec 17 '13 at 22:19









          sparticvs

          1,909918




          1,909918






















              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.






              share|improve this answer


























                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.






                share|improve this answer
























                  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.






                  share|improve this answer














                  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.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited 12 mins ago









                  Community♦

                  1




                  1










                  answered Dec 17 '13 at 22:16









                  Joseph R.

                  27.6k370113




                  27.6k370113



























                       

                      draft saved


                      draft discarded















































                       


                      draft saved


                      draft discarded














                      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













































































                      Popular posts from this blog

                      How to check contact read email or not when send email to Individual?

                      Bahrain

                      Postfix configuration issue with fips on centos 7; mailgun relay