Using listdir realpath abspath with symbolic links

5.1k views Asked by At

Something that I don't understand :
In a shell :

mkdir -p /tmp/toto/titi/tutu    
touch /tmp/toto/tata    
ln -s /tmp/toto/tata /tmp/toto/titi/tutu/     
python    

Then in python:

import os
zeList = os.listdir("/tmp/toto/titi/tutu/")
print os.path.realpath(zeList[0])
 >'/tata' 
print os.path.abspath(zeList[0])
 >'/tata' 

The expected result should be : /tmp/toto/tata (or /tmp/toto/titi/tutu/tata). Can anyone explain this result ?

2

There are 2 answers

0
Martijn Pieters On BEST ANSWER

os.listdir() returns base filenames, not full paths:

>>> import os
>>> os.listdir("/tmp/toto/titi/tutu/")
['tata']

Without a path, the file is then considered relative to the current working directory:

>>> os.getcwd()
'/Users/mj/Development/venvs/stackoverflow-2.7'
>>> os.path.realpath('tata')
'/Users/mj/Development/venvs/stackoverflow-2.7/tata'

Join the filename with the path first:

testdir = "/tmp/toto/titi/tutu/"
zeList = [os.path.join(testdir, fname) for fname in os.listdir(testdir)]

Now the symbolic link is properly replaced:

>>> testdir = "/tmp/toto/titi/tutu/"
>>> zeList = [os.path.join(testdir, fname) for fname in os.listdir(testdir)]
>>> print os.path.realpath(zeList[0])
/private/tmp/toto/tata
>>> print os.path.abspath(zeList[0])
/tmp/toto/titi/tutu/tata
0
nneonneo On

listdir returns filenames, not paths. Therefore you are passing a relative path to realpath which is interpreted relative to your working directory /.

Use os.path.realpath(os.path.join(..., zeList[0])) for correct results.