How to get a symlink in Python?

Using Python, I need to check if hundreds of symbolic links are correct and recreate them when not. Now I have to compare the real paths of what I want and what I have, but it is slow because it is over NFS with auto-mount.

Otherwise, I will start the subprocess using the ls -l command and work in the list of returned strings. I would prefer a better solution using the Python library ...

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

Edit2: Maybe I didn’t put it right. What I mean by a valid symbolic link is "a link that points to a predefined path, even if it does not exist." Therefore, I need to verify that:

 link_name_1 -> target_1 link_name_2 -> target_2 

This is why I need to extract goals, not real paths. Then I compare them with a link (dictionary). So my question is: how to extract the target path?

+19
source share
4 answers

The problem with os.readlink() is that it will only allow one link step. We may have a situation where A refers to another link B and link B hangs.

 $ 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 goal.

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

But in most cases, I assume that we are interested in the permitted path. So pathlib can help here:

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

For older versions of Python:

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

You need to look at os.readlink() .

+12
source

To determine if a directory entry is a symbolic link, use this:

os.path.islink (path)

Returns True if the path refers to a directory entry, which is a symbolic link. Always False if symbolic links are not supported.

0
source

To determine if the link is broken, you can os.walk and check os.path.exists(path) , which will return False for the broken link. Then you can use os.path.realpath(path) to find out what the link should point to.
Something like (not verified):

 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))) 
0
source

Source: https://habr.com/ru/post/1234097/


All Articles