Coder Perfect

how to discover the full(absolute path) of the target file of a symbolic link or soft link in python

Problem

when I’m giving ls -l /etc/fonts/conf.d/70-yes-bitmaps.conf

lrwxrwxrwx <snip> /etc/fonts/conf.d/70-yes-bitmaps.conf -> ../conf.avail/70-yes-bitmaps.conf

So, for a symbolic link or soft link, how do you find the full(absolute path) of the target file in Python?

If i use

os.readlink(‘/etc/fonts/conf.d/70-yes-bitmaps.conf’)

it outputs

../conf.avail/70-yes-bitmaps.conf

However, because I require the absolute path rather than the relative path, my desired output must be,

/etc/fonts/conf.avail/70-yes-bitmaps.conf

how to replace the.. with the entire path of the symbolic link or soft link file’s parent directory

Asked by duhhunjonn

Solution #1

os.path.realpath(path)

The canonical path of the supplied filename is returned by os.path.realpath, which removes any symbolic links from the path.

Answered by unutbu

Solution #2

As unutbu suggests, the appropriate response is os.path.realpath(path), which returns the canonical path of the supplied filename while also resolving any symbolic links to their targets. However, it isn’t working under Windows.

To solve this bug, I generated a patch for Python 3.2 and uploaded it to:

http://bugs.python.org/issue9949

The realpath() method in Python32Libntpath.py is now fixed.

I’ve also uploaded it to my server:

http://www.burtonsys.com/ntpath_fix_issue9949.zip

Unfortunately, the bug exists in Python 2.x as well, and I am unaware of a solution.

Answered by Dave Burton

Solution #3

http://docs.python.org/library/os.path.html#os.path.abspath

Depending on whether you’re working in the current working directory or elsewhere, you can also use joinpath() and normpath(). For you, normpath() might be a better option.

Specifically:

os.path.normpath( 
  os.path.join( 
    os.path.dirname( '/etc/fonts/conf.d/70-yes-bitmaps.conf' ), 
    os.readlink('/etc/fonts/conf.d/70-yes-bitmaps.conf') 
  ) 
)

Answered by eruciform

Solution #4

For filesystem operations, I recommend using the pathlib library.

import pathlib

x = pathlib.Path('lol/lol/path')
x.resolve()

Path.resolve(strict=False) documentation: resolve any symlinks and make the path absolute. The path object gets replaced with a new one.

Answered by Alex

Solution #5

On windows 10, python 3.5, os.readlink(“C:\\Users\PP”) where “C:\Users\PP” is a symbolic link (not a junction link) works.

It returns the directory’s absolute path.

This also works on Ubuntu 16.04 with Python 3.5.

Answered by alpha_989

Post is based on https://stackoverflow.com/questions/3220755/how-to-find-the-target-files-fullabsolute-path-of-the-symbolic-link-or-soft-l