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?
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'
Vous devez regarder os.readlink()
.
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)))
Pour déterminer si une entrée de répertoire est un lien symbolique, utilisez ceci:
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.