如何在Python中查找符号链接或软链接的目标文件的完整(绝对)路径

84

当我输入命令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

如何在Python中查找符号链接或软链接的目标文件的完整(绝对)路径?

如果我使用

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

它会输出

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

但我需要的是绝对路径而不是相对路径,所以我的期望输出应该是

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

如何将..替换为符号链接或软链接文件的父目录的实际完整路径。


os.readlink 应该在 Ubuntu/Windows,Python 3.5 上工作。我刚刚测试过了:https://dev59.com/PHA75IYBdhLWcg3wkaCA#49590179 - alpha_989
6个回答

149
os.path.realpath(path)

os.path.realpath 函数返回指定文件名的规范路径,会消除路径中遇到的所有符号链接。


5
在Windows 7下,Python 3.2中的os.path.realpath未能消除符号链接。(一个bug?) - Dave Burton
2
嗯...我看到这个问题已经持续了1.5年了: http://bugs.python.org/issue9949 - Dave Burton
2
是的,我也遇到了同样的问题,三年过去了 :c - Cobertos
2
在Python3中,如果您正在使用“Path”对象,则可以通过执行“path.resolve()”来完成相同的操作。 - rogueleaderr
2
Python 3.8已经解决了Windows的问题:“自版本3.8起,符号链接和联接现在在Windows上得到了解决。” - Diego
显示剩余4条评论

17
如 unutbu 所说,os.path.realpath(path)应该是正确答案,返回指定文件名的规范路径,解析任何符号链接到其目标。但在Windows下它有问题。
我已经为Python 3.2创建了一个补丁来修复这个bug,并将其上传到: http://bugs.python.org/issue9949 它修复了Python32\Lib\ntpath.py中的realpath()函数。
我还将它放在了我的服务器上,位置在: http://www.burtonsys.com/ntpath_fix_issue9949.zip 不幸的是,这个bug也存在于Python 2.x中,我不知道是否有修复方法。

os.path.realpath和ls -l在挂载驱动器上有不同的结果。 - CS QGB

12

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

还有joinpath()normpath(),具体取决于你是在当前工作目录还是使用其他地方的内容。对你来说,normpath()可能更直接。

具体而言:

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') 
  ) 
)

2
但要注意:如果您传递的路径不是符号链接,则readlink会发生异常并显示以下错误信息: OSError: [Errno 22] Invalid argument: 'your-path' - Diego

10

我建议使用pathlib库进行文件系统操作。

import pathlib

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

Path.resolve(strict=False) 的文档:将路径转换为绝对路径,并解决所有符号链接。返回一个新的路径对象。


1
在Windows 10,Python 3.5上,os.readlink("C:\\Users\PP")可以使用,其中"C:\Users\PP"是一个符号链接(而不是连接点)。
它返回目录的绝对路径。
同样地,在Ubuntu 16.04,Python 3.5上也可以使用。

0

文档中建议使用os.path.join()

结果可能是绝对路径或相对路径;如果是相对路径,则可以使用os.path.join(os.path.dirname(path), result)将其转换为绝对路径。


os.path.abspath ? - dmitry_romanov
1
不需要,@dmitry_romanov。如果你只是调用 os.path.abspath(result),它就不知道路径应该从哪里开始了。这就是为什么你需要传入 path 的原因。如果 result 已经是绝对路径,那么 join 就很聪明了。从文档中可以看到:"如果一个组件是绝对路径,所有之前的组件都会被丢弃,连接将从绝对路径组件继续进行。" - Don Kirkby

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接