How to get symlink target in Python?

耗尽温柔 提交于 2019-11-29 16:32:53

问题


Using Python, I need to check whether hundreds of symlinks are correct and recreate them when not. What I do now is to compare real paths of what I want and what I have, but it's slow because it's over NFS with an automount.

Otherwise I'm going to run a subprocess with the command 'ls -l' and work on the list of strings returned. I would prefer a better solution, using a Python library...

Edit1: I have: link_name -> link_target and then link_target -> a_real_file. What I need is to extract link_target from link_name, not a_real_file. I don't care if the real file does not exist.

Edit2: Maybe I did not express correctly. What I mean by a correct symlink is 'a link that point to a predefined path, even if it does not exist'. So I need to check that:

link_name_1 -> target_1
link_name_2 -> target_2

That's why I need to extract targets, not the real paths. Then I compare them to a reference (dictionary). So my question is: How do I extract the target path?


回答1:


The problem with os.readlink() is it will only resolve 1 step of the link. We can have a situation where A links to another link B, and B link is dangling.

$ ln -s /tmp/example/notexist /tmp/example/B
$ ln -s /tmp/example/B /tmp/example/A
$ ls -l /tmp/example
A -> /tmp/example/B
B -> /tmp/example/notexist

Now in Python, os.readlink gives you the first target.

>>> import os
>>> os.readlink('A')
'/tmp/example/B'

But in most situations I assume we are interested in the resolved path. So pathlib can help here:

>>> from pathlib import Path
>>> Path('A').resolve()
PosixPath('/tmp/example/notexist')

For older Python versions:

>>> os.path.realpath('A')
'/tmp/example/notexist'



回答2:


You need to look at os.readlink().




回答3:


To determine if a directory entry is a symlink use this:

os.path.islink(path)

Return True if path refers to a directory entry that is a symbolic link. Always False if symbolic links are not supported.




回答4:


To determine if a link is broken, you can, os.walk and test os.path.exists(path) which will return False for a broken link. You can then use os.path.realpath(path) to find out what the link is supposed to be pointing to.
Something like (untested):

for root, dirs, files in os.walk('<path>'):
    for file in files:
         f = os.join(root, file)
         if os.path.islink(f) and not os.path.exists(f):
             print("Broken: {} -> {}".format(f, os.path.realpath(f)))


来源:https://stackoverflow.com/questions/33232417/how-to-get-symlink-target-in-python

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!