how to find the target file's full(absolute path) of the symbolic link or soft link in python
Asked Answered
I

6

85

when i give 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 to find the target file's full(absolute path) in python,

If i use

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

it outputs

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

but i need the absolute path not the relative path, so my desired output must be,

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

how to replace the .. with the actual full path of the parent directory of the symbolic link or soft link file.

Irruptive answered 10/7, 2010 at 20:36 Comment(1)
os.readlink should work on ubuntu/windows, python 3.5. Just tested it: https://mcmap.net/q/239384/-how-to-find-the-target-file-39-s-full-absolute-path-of-the-symbolic-link-or-soft-link-in-pythonBlooded
U
151
os.path.realpath(path)

os.path.realpath returns the canonical path of the specified filename, eliminating any symbolic links encountered in the path.

Umbrageous answered 10/7, 2010 at 20:46 Comment(9)
os.path.realpath doesn't eliminate symbolic links in Python 3.2 under Windows 7. (A bug?)Rodneyrodolfo
Hmmm... I see that this has been an open bug for 1.5 years: bugs.python.org/issue9949Rodneyrodolfo
Yup getting this same problem, 3 years later :cYancy
in Python3, if you're using a Path object, you can do the same thing by doing path.resolve()Cabrera
If C:\\Users\\PP is a symlink to another directory, in Windows 10 using python 3.5, os.path.realpath("C:\\Users\PP")basically returns the symlink path, not the real path.Blooded
The Windows issue is fixed in Python 3.8: "Changed in version 3.8: Symbolic links and junctions are now resolved on Windows."Reputation
Note that this depends on your current directory. Docs say "On most platforms, this is equivalent to calling the function normpath() as follows: normpath(join(os.getcwd(), path))".Goldsmith
This assumes that your working directory is at the file with the symlinkTeat
os.path.realpath and ls -l have different results on mount driverIntermarriage
R
18

As unutbu says, os.path.realpath(path) should be the right answer, returning the canonical path of the specified filename, resolving any symbolic links to their targets. But it's broken under Windows.

I've created a patch for Python 3.2 to fix this bug, and uploaded it to:

http://bugs.python.org/issue9949

It fixes the realpath() function in Python32\Lib\ntpath.py

I've also put it on my server, here:

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

Unfortunately, the bug is present in Python 2.x, too, and I know of no fix for it there.

Rodneyrodolfo answered 10/3, 2012 at 1:38 Comment(1)
os.path.realpath and ls -l have different results on mount driverIntermarriage
S
12

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

also joinpath() and normpath(), depending on whether you're in the current working directory, or you're working with things elsewhere. normpath() might be more direct for you.

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') 
  ) 
)
Sundowner answered 10/7, 2010 at 20:39 Comment(1)
Be warned though: should you pass a path which is not a symlink to readlink it will get angry and give the following exception: OSError: [Errno 22] Invalid argument: 'your-path'Reputation
C
12

I recommend using pathlib library for filesystem operations.

import pathlib

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

Documentation for Path.resolve(strict=False): make the path absolute, resolving any symlinks. A new path object is returned.

Crowded answered 21/2, 2019 at 17:59 Comment(0)
B
1

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 absolute path to the directory.

This works on Ubuntu 16.04, python 3.5 as well.

Blooded answered 31/3, 2018 at 16:49 Comment(0)
A
0

The documentation says to use os.path.join():

The result may be either an absolute or relative pathname; if it is relative, it may be converted to an absolute pathname using os.path.join(os.path.dirname(path), result).

Athalla answered 9/11, 2017 at 23:26 Comment(2)
os.path.abspath ?Boycott
Not needed, @dmitry_romanov. If you just called os.path.abspath(result), it wouldn't know where the path should start. That's why you need to pass in path. If result is already an absolute path, then join is smart. From the docs: "If a component is an absolute path, all previous components are thrown away and joining continues from the absolute path component."Athalla

© 2022 - 2024 — McMap. All rights reserved.