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?
  • 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 – loopbackbee 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

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
$ PWD='' bash -c pwd

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).

  • it's useful to know that you clear PWD like so, but by itself this doesn't answer the questions I mentioned – loopbackbee 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! – loopbackbee 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 '18 at 6:59

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.