web-dev-qa-db-fra.com

Comment obtenir une cible de lien symbolique en Python?

En utilisant Python, je dois vérifier si des centaines de liens symboliques sont corrects et les recréer dans le cas contraire. Ce que je fais maintenant est de comparer les chemins réels de ce que je veux et de ce que j'ai, mais c'est lent car c'est sur NFS avec un montage automatique.

Sinon, je vais exécuter un sous-processus avec la commande 'ls -l' et travailler sur la liste des chaînes retournées. Je préférerais une meilleure solution, en utilisant une bibliothèque Python ...

Edit1: J'ai: link_name -> link_target puis link_target -> a_real_file. Ce dont j'ai besoin, c'est d'extraire link_target de link_name, ne pas a_real_file. Je me fiche que le vrai fichier n'existe pas.

Edit2: Peut-être que je n'ai pas exprimé correctement. Ce que je veux dire par un lien symbolique correct est " un lien qui pointe vers un chemin prédéfini, même s'il n'existe pas ". Je dois donc vérifier que:

link_name_1 -> target_1
link_name_2 -> target_2

C'est pourquoi j'ai besoin d'extraire des cibles, pas les vrais chemins. Ensuite, je les compare à une référence (dictionnaire). Ma question est donc la suivante: comment extraire le chemin cible?

20
zorggy

Le problème avec os.readlink() est qu'il ne résoudra qu'une étape du lien. Nous pouvons avoir une situation où A liens vers un autre lien B, et B lien est pendant.

$ 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

Maintenant en Python, os.readlink vous donne la première cible.

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

Mais dans la plupart des situations, je suppose que nous sommes intéressés par le chemin résolu. Donc pathlib peut vous aider ici:

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

Pour les anciennes versions Python:

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

Vous devez regarder os.readlink() .

12
Armin Rigo

Pour déterminer si un lien est rompu, vous pouvez, os.walk Et tester os.path.exists(path) qui renverra False pour un lien rompu. Vous pouvez ensuite utiliser os.path.realpath(path) pour savoir vers quoi le lien est censé pointer.
Quelque chose comme (non testé):

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
AChampion

Pour déterminer si une entrée de répertoire est un lien symbolique, utilisez ceci:

os.path.islink (chemin)

Renvoie True si chemin fait référence à une entrée de répertoire qui est un lien symbolique. Toujours faux si les liens symboliques ne sont pas pris en charge.

0
Madhavan