Expand a relative path but not follow any symlink in the path in Python
Question: This is a subtle question, I know, but I hope you can bear with me for a
moment.

Suppose `/tmp/dir` is a symlink to `/home/user/some/dir`. Suppose also that
your current working directory is `/tmp/dir`.

Even expanding something like `.` does not seem to be possible, as
`os.getcwd()` returns `/home/user/some/dir` instead of `/tmp/dir`, which is
what `pwd` command returns. Relative dir can also be `../dir/../dir/subdir`,
`.././././dir/foo`, etc.

So my question: Is there any reliable function that does path expansion of a
relative path but does not follow the symlink that may exist in the relative
path. In case of `../dir/../dir/subdir`, for example, I would like to get
`/tmp/dir/subdir` and NOT `/home/user/some/dir/subdir`.

Just to avoid getting something I do not want, the answer is NOT
`os.path.abspath`, `os.path.realpath`, `os.path.expanduser`, or
`os.path.relpath`.


Answer: Seems as if [you're not the
first](http://stackoverflow.com/questions/8390502/how-to-make-gnu-make-stop-
de-referencing-symbolic-links-to-directories) to notice this odd behavior of
[`chdir(2)`](http://linux.die.net/man/2/chdir).

There's nothing about it in the Linux manpage, but [a similar
page](http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=/apis/chdir.htm)
says...

> `int chdir(const char *path);`
>
> [...]
>
> The **chdir()** function makes the directory named by _path_ the new current
> directory. If the last component of _path_ is a symbolic link, **chdir()**
> resolves the contents of the symbolic link. If the **chdir()** function
> fails, the current directory is unchanged.

...although with no explanation as to why it resolves the symbolic link.

So, you can't technically have a current working directory of `/tmp/dir`, even
if your shell claims otherwise.

However, you can exploit the fact that the shell's built-in `cd` command sets
the environment variable `PWD` to the value you entered, so you can do this...

    
    
    $ cd /tmp/dir
    $ python
    >>> import os
    >>> os.getcwd()
    '/home/user/some/dir'
    >>> os.environ['PWD']
    '/tmp/dir'
    >>> os.path.normpath(os.path.join(os.environ['PWD'], '../dir/../dir/subdir'))
    '/tmp/dir/subdir'
    

...although it may fail in cases when the process wasn't started from a shell.

