How to get the symbolic path instead of real path?
Asked Answered
P

3

11

Suppose I have a path named:

/this/is/a/real/path

Now, I create a symbolic link for it:

/this/is/a/link  -> /this/is/a/real/path

and then, I put a file into this path:

/this/is/a/real/path/file.txt

and cd it with symbolic path name:

cd /this/is/a/link

now, pwd command will return the link name:

> pwd
/this/is/a/link

and now, I want to get the absolute path of file.txt as:

/this/is/a/link/file.txt

but with python's os.abspath() or os.realpath(), they all return the real path (/this/is/a/real/path/file.txt), which is not what I want.

I also tried subprocess.Popen('pwd') and sh.pwd() , but also get the real path instead of symlink path.

How can I get the symbolic absolute path with python?

Update

OK, I read the source code of pwd so I get the answer.

It's quite simple: just get the PWD environment variable.

This is my own abspath to satify my requirement:

def abspath(p):
    curr_path = os.environ['PWD']
    return os.path.normpath(os.path.join(curr_path, p))
Pyridoxine answered 23/7, 2013 at 8:39 Comment(5)
Why do you need this? What are you really trying to do?Georg
I want to use cscope to browse a work project, it contains Chinese chars in its path(and I have no permission to modify). but cscope seems not support it. So I want to use a symlink and use a script to generate cscope.files, and then..., there is the problem.Pyridoxine
That may have been a better questions which would avoid the downvotesGeorg
this is my first question on stackoverflow. I have no idea about how to improve it to be a better questionPyridoxine
It is not important what they are trying to do - this issue will reach thousands of people who are invariably trying to do something else and just need the question answered as asked...Gaudery
S
16

The difference between os.path.abspath and os.path.realpath is that os.path.abspath does not resolve symbolic links, so it should be exactly what you are looking for. I do:

/home/user$ mkdir test
/home/user$ mkdir test/real
/home/user$ mkdir test/link
/home/user$ touch test/real/file
/home/user$ ln -s /home/user/test/real/file test/link/file
/home/user$ ls -lR test

  test:
  d... link
  d... real

  test/real:
  -... file

  test/link:
  l... file -> /home/user/test/real/file

/home/user$ python

  ... python 3.3.2 ...
  >>> import os
  >>> print(os.path.realpath('test/link/file'))
  /home/user/test/real/file
  >>> print(os.path.abspath('test/link/file'))
  /home/user/test/link/file

So there you go. How are you using os.path.abspath that you say it resolves your symbolic link?

Supraorbital answered 23/7, 2013 at 9:17 Comment(6)
Maybe he is doing os.path.abspath(".") after changing to the symlink directory, which does return the real directory.Belinda
But once you are inside the real directory, there isn't a way to determine how you got there anyway, so there isn't a way to retrieve the absolute path (or for that matter, even the base name) of the symbolic link. Or am I wrong?Supraorbital
According to him (and I just confirmed), if you go into a symlinked directory and run pwd (outside python), it gives you the symlink path. But he may not need to go into a directory and determine where he is from there. Maybe it's good enough to define the starting point and then keep track of where he is, in which case your suggestion would work.Belinda
What is the practical difference between the real and link path? Are there some activities that you can't do to a link (or real) path that you could accomplish with the other? The only thing I can think is whether you're able to access a resource in your python path or not (if the link path is in the python path but the real path is not - could this happen?)Handedness
@Handedness In my case I want to CD to a directory provided by a tool, and the real directory pointed to by the symlink may be subject to change. If I follow the symlink I always end up in the right (most recent) location.Mandie
No, I had got the same result when calling os.path.abspath("../") and os.path.realpath("../"). I am using python3.6.5, in CentOS7.6. The Update of the asker is the good answerInadvertency
B
0

You can do this to traverse the directory:

for root, dirs, files in os.walk("/this/is/a/link"):
    for file in files:
        os.path.join(root, file)

This way you will get the path to each file, prefixed with the symlink name instead of the real one.

Belinda answered 23/7, 2013 at 9:34 Comment(0)
A
-1

from python 2.7.3 document:

os.path.abspath(path)¶

Return a normalized absolutized version of the pathname path. On most platforms, this is equivalent to normpath(join(os.getcwd(), path)).

the os.getcwd() will return a real path. e.g.

/home/user$ mkdir test
/home/user$ cd test
/home/user/test$ mkdir real
/home/user/test$ ln -s real link
/home/user/test$ cd link
/home/user/test/link$ python

  >>> import os
  >>> os.getcwd()
  '/home/user/test/real'
  >>> os.path.abspath("file")
  '/home/user/test/real/file'
  >>> os.path.abspath("../link/file")
  '/home/user/test/link/file'

or

/home/user/test/link$ cd ..
/home/user/test$ python

  >>> import os
  >>> os.path.abspath("link/file")
  '/home/user/test/link/file'
Absentee answered 23/7, 2013 at 9:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.