Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to get the realpath of a symbolic link?

13 views
Skip to first unread message

Peng Yu

unread,
Oct 31, 2009, 3:03:20 AM10/31/09
to pytho...@python.org
Suppose that I have the following directory and files. I want to get
the canonical path of a file, a directory or a symbolic link.
For example, for 'b' below, I want to get its canonical path as
'/private/tmp/abspath/b'.

However, os.path.abspath('b') gives me '/private/tmp/abspath/b', but
os.path.abspath('/tmp/abspath/b') gives me '/tmp/abspath/b'.
The results are not the same. So, neither os.path.abspath or
os.path.realpath gives me what I want.

I'm wondering if there is a way to get the canonical path
'/private/tmp/abspath/b', no matter whether the argument is 'b' or
'/tmp/abspath/b'.

$./test.py
/private/tmp/abspath/a
/private/tmp/abspath/a
/private/tmp/abspath/a
/private/tmp/abspath/a
/private/tmp/abspath/a
/private/tmp/abspath/b
/tmp/abspath/a
/tmp/abspath/b
$cat test.py
#!/usr/bin/env python

import os.path

print os.path.realpath('a')
print os.path.realpath('b')
print os.path.realpath('/tmp/abspath/a')
print os.path.realpath('/tmp/abspath/b')

print os.path.abspath('a')
print os.path.abspath('b')
print os.path.abspath('/tmp/abspath/a')
print os.path.abspath('/tmp/abspath/b')
$pwd
/tmp/abspath
$gls -Rgtra
.:
total 8
-rw-r--r-- 1 wheel 0 2009-10-31 01:52 a
lrwxr-xr-x 1 wheel 1 2009-10-31 01:52 b -> a
-rwx--x--x 1 wheel 312 2009-10-31 01:54 test.py
drwx------ 5 wheel 170 2009-10-31 01:54 .
drwxrwxrwt 23 wheel 782 2009-10-31 01:56 ..
$gls -lgtr /tmp
lrwxr-xr-x 1 admin 11 2009-05-21 04:28 /tmp -> private/tmp

Emile van Sebille

unread,
Oct 31, 2009, 12:26:44 PM10/31/09
to pytho...@python.org
On 10/31/2009 12:03 AM Peng Yu said...

> Suppose that I have the following directory and files. I want to get
> the canonical path of a file, a directory or a symbolic link.
> For example, for 'b' below, I want to get its canonical path as
> '/private/tmp/abspath/b'.

So, why isn't realpath working for you? It looks like it is, and it
works that way here:

>>> os.path.realpath('/home/emile/vmlinuz')
'/root/vmlinuz-2.4.7-10'


Emile

Peng Yu

unread,
Oct 31, 2009, 1:11:35 PM10/31/09
to pytho...@python.org

My definition of 'realpath' is different from the definition of
'os.path.realpath'. But I'm not short what term I should use to
describe. I use the following example to show what I want.

In my example in the original post,

'/tmp/abspath/b' is a symbolic link to '/tmp/abspath/a' and '/tmp' is
a symbolic link to '/private/tmp'.

Therefore, I want to get '/private/tmp/abspath/b', rather than
'/private/tmp/abspath/a', as the canonical path of 'b'.

If the argument is a symbolic link os.path.realpath will return the
actually target of the symbolic link. However, I want the path of the
symbolic link rather than the path of the target.

Hope this is clear.

Emile van Sebille

unread,
Oct 31, 2009, 2:10:24 PM10/31/09
to pytho...@python.org
On 10/31/2009 10:11 AM Peng Yu said...

>
> My definition of 'realpath' is different from the definition of
> 'os.path.realpath'. But I'm not short what term I should use to
> describe. I use the following example to show what I want.
>
> In my example in the original post,
>
> '/tmp/abspath/b' is a symbolic link to '/tmp/abspath/a' and '/tmp' is
> a symbolic link to '/private/tmp'.
>
> Therefore, I want to get '/private/tmp/abspath/b', rather than
> '/private/tmp/abspath/a', as the canonical path of 'b'.
>

It still looks like it works here. I've set up a similar structure and
appear to get the results you're asking for using os.path.realpath.

# pwd
/home/emile
# ls -l
drwxr-xr-x 3 root root 4096 2009-10-31 10:25 private
lrwxrwxrwx 1 root root 11 2009-10-31 10:25 tmp -> private/tmp

# pwd
/home/emile/tmp/abspath
# ls -l
-rw-r--r-- 1 root root 10 2009-10-31 10:25 a
lrwxrwxrwx 1 root root 1 2009-10-31 10:26 b -> a

Python 2.6.3 (r263:75183, Oct 15 2009, 15:03:49) [GCC 4.3.2] on linux2
>>> import os
>>> os.path.realpath('/home/emile/tmp/a')
'/home/emile/private/tmp/a'
>>> os.path.realpath('/home/emile/tmp/b')
'/home/emile/private/tmp/b'

> If the argument is a symbolic link os.path.realpath will return the
> actually target of the symbolic link.
> However, I want the path of the
> symbolic link rather than the path of the target.

Which is what I got above.

>
> Hope this is clear.

Terry Reedy

unread,
Oct 31, 2009, 2:46:02 PM10/31/09
to pytho...@python.org
Peng Yu wrote:
> On Sat, Oct 31, 2009 at 11:26 AM, Emile van Sebille <em...@fenx.com> wrote:
>> On 10/31/2009 12:03 AM Peng Yu said...
>>> Suppose that I have the following directory and files. I want to get
>>> the canonical path of a file, a directory or a symbolic link.
>>> For example, for 'b' below, I want to get its canonical path as
>>> '/private/tmp/abspath/b'.
>> So, why isn't realpath working for you? It looks like it is, and it works
>> that way here:
>>
>>>>> os.path.realpath('/home/emile/vmlinuz')
>> '/root/vmlinuz-2.4.7-10'
>
> My definition of 'realpath' is different from the definition of
> 'os.path.realpath'. But I'm not short what term I should use to
> describe. I use the following example to show what I want.
>
> In my example in the original post,
>
> '/tmp/abspath/b' is a symbolic link to '/tmp/abspath/a' and '/tmp' is
> a symbolic link to '/private/tmp'.
>
> Therefore, I want to get '/private/tmp/abspath/b', rather than
> '/private/tmp/abspath/a', as the canonical path of 'b'.
>
> If the argument is a symbolic link os.path.realpath will return the
> actually target of the symbolic link. However, I want the path of the
> symbolic link rather than the path of the target.
>
> Hope this is clear.

I suspect that you will have to write your own code for your own
function. os and os.path are written in Python, so look at the code for
realpath and modify it for your modified definition.

Terry Jan Reedy

Peng Yu

unread,
Oct 31, 2009, 3:24:31 PM10/31/09
to pytho...@python.org
On Sat, Oct 31, 2009 at 1:10 PM, Emile van Sebille <em...@fenx.com> wrote:
> On 10/31/2009 10:11 AM Peng Yu said...
>>
>> My definition of 'realpath' is different from the definition of
>> 'os.path.realpath'. But I'm not short what term I should use to
>> describe. I use the following example to show what I want.
>>
>> In my example in the original post,
>>
>> '/tmp/abspath/b' is a symbolic link to '/tmp/abspath/a' and '/tmp' is
>> a symbolic link to '/private/tmp'.
>>
>> Therefore, I want to get '/private/tmp/abspath/b', rather than
>> '/private/tmp/abspath/a', as the canonical path of 'b'.
>>
>
> It still looks like it works here.  I've set up a similar structure and
> appear to get the results you're asking for using os.path.realpath.
>
> # pwd
> /home/emile
> # ls -l
> drwxr-xr-x 3 root root 4096 2009-10-31 10:25 private
> lrwxrwxrwx 1 root root   11 2009-10-31 10:25 tmp -> private/tmp
>
> # pwd
> /home/emile/tmp/abspath
> # ls -l
> -rw-r--r-- 1 root root 10 2009-10-31 10:25 a
> lrwxrwxrwx 1 root root  1 2009-10-31 10:26 b -> a
>
> Python 2.6.3 (r263:75183, Oct 15 2009, 15:03:49) [GCC 4.3.2] on linux2
>>>> import os
>>>> os.path.realpath('/home/emile/tmp/a')
> '/home/emile/private/tmp/a'
>>>> os.path.realpath('/home/emile/tmp/b')
> '/home/emile/private/tmp/b'
>
>> If the argument is a symbolic link os.path.realpath will return the
>> actually target of the symbolic link. However, I want the path of the
>> symbolic link rather than the path of the target.
>
> Which is what I got above.

I'm curious why we get different results. I tried on both linux and
mac. Both of them give me the same results.

Peng Yu

unread,
Oct 31, 2009, 3:48:15 PM10/31/09
to pytho...@python.org
On Sat, Oct 31, 2009 at 1:46 PM, Terry Reedy <tjr...@udel.edu> wrote:
> Peng Yu wrote:

>>
>> On Sat, Oct 31, 2009 at 11:26 AM, Emile van Sebille <em...@fenx.com>
>> wrote:
>>>
>>> On 10/31/2009 12:03 AM Peng Yu said...
>>>>
>>>> Suppose that I have the following directory and files. I want to get
>>>> the canonical path of a file, a directory or a symbolic link.
>>>> For example, for 'b' below, I want to get its canonical path as
>>>> '/private/tmp/abspath/b'.
>>>
>>> So, why isn't realpath working for you?  It looks like it is, and it
>>> works
>>> that way here:
>>>
>>>>>> os.path.realpath('/home/emile/vmlinuz')
>>>
>>> '/root/vmlinuz-2.4.7-10'
>>
>> My definition of 'realpath' is different from the definition of
>> 'os.path.realpath'. But I'm not short what term I should use to
>> describe. I use the following example to show what I want.
>>
>> In my example in the original post,
>>
>> '/tmp/abspath/b' is a symbolic link to '/tmp/abspath/a' and '/tmp' is
>> a symbolic link to '/private/tmp'.
>>
>> Therefore, I want to get '/private/tmp/abspath/b', rather than
>> '/private/tmp/abspath/a', as the canonical path of 'b'.
>>
>> If the argument is a symbolic link os.path.realpath will return the
>> actually target of the symbolic link. However, I want the path of the
>> symbolic link rather than the path of the target.
>>
>> Hope this is clear.
>
> I suspect that you will have to write your own code for your own function.
> os and os.path are written in Python, so look at the code for realpath and
> modify it for your modified definition.

I find the following two files that define realpath. But I don't find
'realpath' in os.py. I looked at 'os.py'. But I don't understand how
the function realpath is introduced in the name space in os.path.
Would you please let me know?

gfind . ! -path '*backup*' -name "*.py" -type f -exec grep -n "def
realpath" {} \; -printf %p\\n\\n
193:def realpath(path):
./macpath.py

345:def realpath(filename):
./posixpath.py

Wolodja Wentland

unread,
Oct 31, 2009, 6:29:08 PM10/31/09
to pytho...@python.org
On Sat, Oct 31, 2009 at 14:48 -0500, Peng Yu wrote:
> On Sat, Oct 31, 2009 at 1:46 PM, Terry Reedy <tjr...@udel.edu> wrote:
> > Peng Yu wrote:
[ snip ]

> I find the following two files that define realpath. But I don't find
> 'realpath' in os.py. I looked at 'os.py'. But I don't understand how
> the function realpath is introduced in the name space in os.path.
> Would you please let me know?

> gfind . ! -path '*backup*' -name "*.py" -type f -exec grep -n "def
> realpath" {} \; -printf %p\\n\\n
> 193:def realpath(path):
> ./macpath.py
>
> 345:def realpath(filename):
> ./posixpath.py

The os module needs to support different platforms. The os.path module
is actually one of the platform specific ones (ntpath, posixpath,
...) that are imported 'as path' depending on the platform the code is
executed.

Have a look at the source code of the os module:

--- os.py - Python 2.6.3 ---
...
f 'posix' in _names:
...
import posixpath as path

elif 'nt' in _names:
...
import ntpath as path

import nt
__all__.extend(_get_exports_list(nt))
del nt

...

else:
raise ImportError, 'no os specific module found'

sys.modules['os.path'] = path

--- snip ---

If you really want to understand how a module is working then have a
look at its source code. Python is open source --> Use that privilige!

kind regards

Wolodja Wentland

signature.asc

Terry Reedy

unread,
Nov 1, 2009, 12:28:53 AM11/1/09
to pytho...@python.org
Peng Yu wrote:

> I find the following two files that define realpath. But I don't find
> 'realpath' in os.py. I looked at 'os.py'. But I don't understand how
> the function realpath is introduced in the name space in os.path.
> Would you please let me know?
>
> gfind . ! -path '*backup*' -name "*.py" -type f -exec grep -n "def
> realpath" {} \; -printf %p\\n\\n
> 193:def realpath(path):
> ./macpath.py
>
> 345:def realpath(filename):
> ./posixpath.py

That is where realpath is.

0 new messages