Symbolic Link seems to be Contradictory when dealing with ‘../’

The contradiction here is how symlink deal with directory ../ in 2 ways:

  • treat the current path as the result printed by pwd
  • treat the current path as absolute path

I will discuss them with an example (pretty easy to understand).


Considering the following directory hierarchy:

/tmp/
  |__a/
  |  |__b/
  |
  |__sb=./a/b/ -> /tmp/a/b/  # the name `sb' means symbol b;
                             # `sb' is generated by:
                             # [/tmp/]$ ln -s ./a/b/ sb
  1. _

    [/tmp/]$ cd sb  # `pwd' says we are now in /tmp/
                    # let's change to /tmp/a/b/
    
    [/tmp/sb/]$ cd ../  # Now we are in /tmp/a/b/
                        # But what is /tmp/a/b/'s parent dir?
    
    [/tmp/]$   # See?  We didn't come back to /tmp/a/ BUT /tmp/
    

    It means that the current parent dir is the second from the right printed by pwd.

  2. Let’s add a symlink into dir /tmp/a/b/:

    /tmp/
      |__a/
      |  |__b/
      |     |__sa=../ -> /tmp/a/  # [/tmp/a/b/]$ ln -s ../ sa
      |
      |__sb=./a/b/ -> /tmp/a/b/
    

    This time, we will come back to the actual parent dir of /tmp/a/b/:

    [/tmp/]$ cd sb  # change to /tmp/a/b/
    
    [/tmp/sb/]$ cd sa  # sa=../
                       # /tmp/sb/=/tmp/a/b/
                       #   ^    or     ^
    
    [/tmp/sb/sa/]$ ls --classify
    b/                 # ???
                       # We are now in /tmp/a/ because there is a b/ here!
    

    So Why this time it chooses to refer to the absolute path to determine the parent dir?


The contradiction arises when it comes to ../, but I suspect the same thing happens when it comes to relative path.

All the above operations are tested on CentOS 7.9