Understanding directory symlinks traversals and the parent directory

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











up vote
8
down vote

favorite
3












Let's say you have directories /dir1 and /dir2/linked, where the latter is a symlink to the former.



When you cd to linked and pwd, you get the output /dir2/linked. If you then cd .., you'll be put on /dir2. This behaviour is consistent with the concept of you being in /dir2/linked before. However, as I understand it, the parent directory (..) of any directory is stored in the directory inode (i.e.:physically in the disk). Obviously, since /dir2/linked is really /dir1, the parent directory on the inode must be /



To further complicate matters, while inside /dir2/linked, the outputs of ls .. and cd .. ; ls . are different! It seems like cd honors the symlinked path, while ls honors the "physical" path. As mentioned in this question, there's cd -P for this use case, though.



man pwd mentions "physical" and "logical" working directories, but I still have a few questions at this point:



  • Is this behaviour always provided by the PWD environment variable, as mentioned in man pwd?

  • Why do default cd and ls have different behaviours, if they're both shell commands (i.e.: not programs)?

  • Does the typical program (not shell command) use PWD instead of the physical path? I realize it's up to the implementation, but is there any rule of thumb?









share|improve this question



















  • 1




    A lot of info in this answer
    – Stéphane Chazelas
    Jan 23 '15 at 11:11






  • 1




    @StéphaneChazelas That's a fantastic answer, thanks for sharing
    – goncalopp
    Jan 23 '15 at 12:53










  • You're welcome. Please feel free to copy-paste text from there if you plan to make your own answer to your own question.
    – Stéphane Chazelas
    Jan 23 '15 at 13:17














up vote
8
down vote

favorite
3












Let's say you have directories /dir1 and /dir2/linked, where the latter is a symlink to the former.



When you cd to linked and pwd, you get the output /dir2/linked. If you then cd .., you'll be put on /dir2. This behaviour is consistent with the concept of you being in /dir2/linked before. However, as I understand it, the parent directory (..) of any directory is stored in the directory inode (i.e.:physically in the disk). Obviously, since /dir2/linked is really /dir1, the parent directory on the inode must be /



To further complicate matters, while inside /dir2/linked, the outputs of ls .. and cd .. ; ls . are different! It seems like cd honors the symlinked path, while ls honors the "physical" path. As mentioned in this question, there's cd -P for this use case, though.



man pwd mentions "physical" and "logical" working directories, but I still have a few questions at this point:



  • Is this behaviour always provided by the PWD environment variable, as mentioned in man pwd?

  • Why do default cd and ls have different behaviours, if they're both shell commands (i.e.: not programs)?

  • Does the typical program (not shell command) use PWD instead of the physical path? I realize it's up to the implementation, but is there any rule of thumb?









share|improve this question



















  • 1




    A lot of info in this answer
    – Stéphane Chazelas
    Jan 23 '15 at 11:11






  • 1




    @StéphaneChazelas That's a fantastic answer, thanks for sharing
    – goncalopp
    Jan 23 '15 at 12:53










  • You're welcome. Please feel free to copy-paste text from there if you plan to make your own answer to your own question.
    – Stéphane Chazelas
    Jan 23 '15 at 13:17












up vote
8
down vote

favorite
3









up vote
8
down vote

favorite
3






3





Let's say you have directories /dir1 and /dir2/linked, where the latter is a symlink to the former.



When you cd to linked and pwd, you get the output /dir2/linked. If you then cd .., you'll be put on /dir2. This behaviour is consistent with the concept of you being in /dir2/linked before. However, as I understand it, the parent directory (..) of any directory is stored in the directory inode (i.e.:physically in the disk). Obviously, since /dir2/linked is really /dir1, the parent directory on the inode must be /



To further complicate matters, while inside /dir2/linked, the outputs of ls .. and cd .. ; ls . are different! It seems like cd honors the symlinked path, while ls honors the "physical" path. As mentioned in this question, there's cd -P for this use case, though.



man pwd mentions "physical" and "logical" working directories, but I still have a few questions at this point:



  • Is this behaviour always provided by the PWD environment variable, as mentioned in man pwd?

  • Why do default cd and ls have different behaviours, if they're both shell commands (i.e.: not programs)?

  • Does the typical program (not shell command) use PWD instead of the physical path? I realize it's up to the implementation, but is there any rule of thumb?









share|improve this question















Let's say you have directories /dir1 and /dir2/linked, where the latter is a symlink to the former.



When you cd to linked and pwd, you get the output /dir2/linked. If you then cd .., you'll be put on /dir2. This behaviour is consistent with the concept of you being in /dir2/linked before. However, as I understand it, the parent directory (..) of any directory is stored in the directory inode (i.e.:physically in the disk). Obviously, since /dir2/linked is really /dir1, the parent directory on the inode must be /



To further complicate matters, while inside /dir2/linked, the outputs of ls .. and cd .. ; ls . are different! It seems like cd honors the symlinked path, while ls honors the "physical" path. As mentioned in this question, there's cd -P for this use case, though.



man pwd mentions "physical" and "logical" working directories, but I still have a few questions at this point:



  • Is this behaviour always provided by the PWD environment variable, as mentioned in man pwd?

  • Why do default cd and ls have different behaviours, if they're both shell commands (i.e.: not programs)?

  • Does the typical program (not shell command) use PWD instead of the physical path? I realize it's up to the implementation, but is there any rule of thumb?






shell directory symlink cd-command






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Aug 26 at 2:32









guntbert

1,0111917




1,0111917










asked Jan 23 '15 at 11:04









goncalopp

1,64211423




1,64211423







  • 1




    A lot of info in this answer
    – Stéphane Chazelas
    Jan 23 '15 at 11:11






  • 1




    @StéphaneChazelas That's a fantastic answer, thanks for sharing
    – goncalopp
    Jan 23 '15 at 12:53










  • You're welcome. Please feel free to copy-paste text from there if you plan to make your own answer to your own question.
    – Stéphane Chazelas
    Jan 23 '15 at 13:17












  • 1




    A lot of info in this answer
    – Stéphane Chazelas
    Jan 23 '15 at 11:11






  • 1




    @StéphaneChazelas That's a fantastic answer, thanks for sharing
    – goncalopp
    Jan 23 '15 at 12:53










  • You're welcome. Please feel free to copy-paste text from there if you plan to make your own answer to your own question.
    – Stéphane Chazelas
    Jan 23 '15 at 13:17







1




1




A lot of info in this answer
– Stéphane Chazelas
Jan 23 '15 at 11:11




A lot of info in this answer
– Stéphane Chazelas
Jan 23 '15 at 11:11




1




1




@StéphaneChazelas That's a fantastic answer, thanks for sharing
– goncalopp
Jan 23 '15 at 12:53




@StéphaneChazelas That's a fantastic answer, thanks for sharing
– goncalopp
Jan 23 '15 at 12:53












You're welcome. Please feel free to copy-paste text from there if you plan to make your own answer to your own question.
– Stéphane Chazelas
Jan 23 '15 at 13:17




You're welcome. Please feel free to copy-paste text from there if you plan to make your own answer to your own question.
– Stéphane Chazelas
Jan 23 '15 at 13:17










1 Answer
1






active

oldest

votes

















up vote
5
down vote



accepted










bash "knows" about symlinks and tracks this info when you use a symlink to enter a directory.



You can check this by doing the following in your example:



$ cd /dir2
$ cd linked
$ pwd
/dir2/linked
$ PWD='' bash -c pwd
/dir1


You need to start the bash with an empty PWD variable, otherwise it uses that trick to display the "fake" path.



Note that ls is a separate program and as such doesn't have bash's knowledge of how you arrived at the current directory, so ls .. will just show the contents of the real parent directory, not relative to the symlink you followed.



Most programs will not depend on the environment variable CWD as there are many ways of starting programs, via the bash shell is just one so it's not reliable to expect CWD to contain the correct value (try setting CWD to something wrong before doing bash -c pwd, you can see it checks the value for sanity).






share|improve this answer






















  • it's useful to know that you clear PWD like so, but by itself this doesn't answer the questions I mentioned
    – goncalopp
    Jan 23 '15 at 12:57










  • Added some more info.
    – wurtel
    Jan 23 '15 at 14:52










  • I was under the impression ls was provided by bash, but you and help convinced me otherwise. That makes things a lot clearer, thanks!
    – goncalopp
    Jan 26 '15 at 10:21










  • PWD is standard in POSIX. You can rely on it to be set. If it is not set, things could break, for example the pwd utility: See also Environment variables.
    – darkfeline
    Jul 15 at 6:59










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: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
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%2f180620%2funderstanding-directory-symlinks-traversals-and-the-parent-directory%23new-answer', 'question_page');

);

Post as a guest






























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
5
down vote



accepted










bash "knows" about symlinks and tracks this info when you use a symlink to enter a directory.



You can check this by doing the following in your example:



$ cd /dir2
$ cd linked
$ pwd
/dir2/linked
$ PWD='' bash -c pwd
/dir1


You need to start the bash with an empty PWD variable, otherwise it uses that trick to display the "fake" path.



Note that ls is a separate program and as such doesn't have bash's knowledge of how you arrived at the current directory, so ls .. will just show the contents of the real parent directory, not relative to the symlink you followed.



Most programs will not depend on the environment variable CWD as there are many ways of starting programs, via the bash shell is just one so it's not reliable to expect CWD to contain the correct value (try setting CWD to something wrong before doing bash -c pwd, you can see it checks the value for sanity).






share|improve this answer






















  • it's useful to know that you clear PWD like so, but by itself this doesn't answer the questions I mentioned
    – goncalopp
    Jan 23 '15 at 12:57










  • Added some more info.
    – wurtel
    Jan 23 '15 at 14:52










  • I was under the impression ls was provided by bash, but you and help convinced me otherwise. That makes things a lot clearer, thanks!
    – goncalopp
    Jan 26 '15 at 10:21










  • PWD is standard in POSIX. You can rely on it to be set. If it is not set, things could break, for example the pwd utility: See also Environment variables.
    – darkfeline
    Jul 15 at 6:59














up vote
5
down vote



accepted










bash "knows" about symlinks and tracks this info when you use a symlink to enter a directory.



You can check this by doing the following in your example:



$ cd /dir2
$ cd linked
$ pwd
/dir2/linked
$ PWD='' bash -c pwd
/dir1


You need to start the bash with an empty PWD variable, otherwise it uses that trick to display the "fake" path.



Note that ls is a separate program and as such doesn't have bash's knowledge of how you arrived at the current directory, so ls .. will just show the contents of the real parent directory, not relative to the symlink you followed.



Most programs will not depend on the environment variable CWD as there are many ways of starting programs, via the bash shell is just one so it's not reliable to expect CWD to contain the correct value (try setting CWD to something wrong before doing bash -c pwd, you can see it checks the value for sanity).






share|improve this answer






















  • it's useful to know that you clear PWD like so, but by itself this doesn't answer the questions I mentioned
    – goncalopp
    Jan 23 '15 at 12:57










  • Added some more info.
    – wurtel
    Jan 23 '15 at 14:52










  • I was under the impression ls was provided by bash, but you and help convinced me otherwise. That makes things a lot clearer, thanks!
    – goncalopp
    Jan 26 '15 at 10:21










  • PWD is standard in POSIX. You can rely on it to be set. If it is not set, things could break, for example the pwd utility: See also Environment variables.
    – darkfeline
    Jul 15 at 6:59












up vote
5
down vote



accepted







up vote
5
down vote



accepted






bash "knows" about symlinks and tracks this info when you use a symlink to enter a directory.



You can check this by doing the following in your example:



$ cd /dir2
$ cd linked
$ pwd
/dir2/linked
$ PWD='' bash -c pwd
/dir1


You need to start the bash with an empty PWD variable, otherwise it uses that trick to display the "fake" path.



Note that ls is a separate program and as such doesn't have bash's knowledge of how you arrived at the current directory, so ls .. will just show the contents of the real parent directory, not relative to the symlink you followed.



Most programs will not depend on the environment variable CWD as there are many ways of starting programs, via the bash shell is just one so it's not reliable to expect CWD to contain the correct value (try setting CWD to something wrong before doing bash -c pwd, you can see it checks the value for sanity).






share|improve this answer














bash "knows" about symlinks and tracks this info when you use a symlink to enter a directory.



You can check this by doing the following in your example:



$ cd /dir2
$ cd linked
$ pwd
/dir2/linked
$ PWD='' bash -c pwd
/dir1


You need to start the bash with an empty PWD variable, otherwise it uses that trick to display the "fake" path.



Note that ls is a separate program and as such doesn't have bash's knowledge of how you arrived at the current directory, so ls .. will just show the contents of the real parent directory, not relative to the symlink you followed.



Most programs will not depend on the environment variable CWD as there are many ways of starting programs, via the bash shell is just one so it's not reliable to expect CWD to contain the correct value (try setting CWD to something wrong before doing bash -c pwd, you can see it checks the value for sanity).







share|improve this answer














share|improve this answer



share|improve this answer








edited Jan 23 '15 at 14:52

























answered Jan 23 '15 at 11:14









wurtel

9,38511324




9,38511324











  • it's useful to know that you clear PWD like so, but by itself this doesn't answer the questions I mentioned
    – goncalopp
    Jan 23 '15 at 12:57










  • Added some more info.
    – wurtel
    Jan 23 '15 at 14:52










  • I was under the impression ls was provided by bash, but you and help convinced me otherwise. That makes things a lot clearer, thanks!
    – goncalopp
    Jan 26 '15 at 10:21










  • PWD is standard in POSIX. You can rely on it to be set. If it is not set, things could break, for example the pwd utility: See also Environment variables.
    – darkfeline
    Jul 15 at 6:59
















  • it's useful to know that you clear PWD like so, but by itself this doesn't answer the questions I mentioned
    – goncalopp
    Jan 23 '15 at 12:57










  • Added some more info.
    – wurtel
    Jan 23 '15 at 14:52










  • I was under the impression ls was provided by bash, but you and help convinced me otherwise. That makes things a lot clearer, thanks!
    – goncalopp
    Jan 26 '15 at 10:21










  • PWD is standard in POSIX. You can rely on it to be set. If it is not set, things could break, for example the pwd utility: See also Environment variables.
    – darkfeline
    Jul 15 at 6:59















it's useful to know that you clear PWD like so, but by itself this doesn't answer the questions I mentioned
– goncalopp
Jan 23 '15 at 12:57




it's useful to know that you clear PWD like so, but by itself this doesn't answer the questions I mentioned
– goncalopp
Jan 23 '15 at 12:57












Added some more info.
– wurtel
Jan 23 '15 at 14:52




Added some more info.
– wurtel
Jan 23 '15 at 14:52












I was under the impression ls was provided by bash, but you and help convinced me otherwise. That makes things a lot clearer, thanks!
– goncalopp
Jan 26 '15 at 10:21




I was under the impression ls was provided by bash, but you and help convinced me otherwise. That makes things a lot clearer, thanks!
– goncalopp
Jan 26 '15 at 10:21












PWD is standard in POSIX. You can rely on it to be set. If it is not set, things could break, for example the pwd utility: See also Environment variables.
– darkfeline
Jul 15 at 6:59




PWD is standard in POSIX. You can rely on it to be set. If it is not set, things could break, for example the pwd utility: See also Environment variables.
– darkfeline
Jul 15 at 6:59

















 

draft saved


draft discarded















































 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f180620%2funderstanding-directory-symlinks-traversals-and-the-parent-directory%23new-answer', 'question_page');

);

Post as a guest













































































Popular posts from this blog

Peggy Mitchell

Palaiologos

The Forum (Inglewood, California)