Vérifiez si le fichier est un lien symbolique en python

91

En python, existe-t-il une fonction pour vérifier si un fichier / répertoire donné est un lien symbolique? Par exemple, pour les fichiers ci-dessous, ma fonction wrapper doit retourner True.

# ls -l
total 0
lrwxrwxrwx 1 root root 8 2012-06-16 18:58 dir -> ../temp/
lrwxrwxrwx 1 root root 6 2012-06-16 18:55 link -> ../log
Bandicoot
la source

Réponses:

136

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 False si les liens symboliques ne sont pas pris en charge.

Par exemple, étant donné:

drwxr-xr-x   2 root root  4096 2011-11-10 08:14 bin/
drwxrwxrwx   1 root root    57 2011-07-10 05:11 initrd.img -> boot/initrd.img-2..

>>> import os.path
>>> os.path.islink('initrd.img')
True
>>> os.path.islink('bin')
False
Levon
la source
7
Sous Windows, les raccourcis apparaissent sous forme de fichiers avec une extension lnket les os.islink('a_shortcut.lnk')retours False.
Evgeni Sergeev
1
@EvgeniSergeev C'est parce que ce ne sont que des fichiers - peut-être une gueule de bois de Windows 9x jours où le seul système de fichiers était FAT / FAT32. Voir ce superuser.com/questions/347930/… pour tous les types de liens symboliques / physiques et de jonctions d'annuaire pris en charge sur NTFS. Cela dit, je ne pense toujours pas que Python les prend en charge.
jmc
9
Et islink () ne fonctionne pas pour les liens symboliques Windows, c'est-à-dire les jonctions. La réponse ne s'applique donc qu'à Unix.
Le parrain
2
Veuillez vous référer à cette réponse stackoverflow.com/questions/27972776/… si vous avez besoin d'une solution Windows.
Le Parrain
1
@TheGodfather: la jonction de répertoires n'est pas un lien symbolique ( IO_REPARSE_TAG_SYMLINK).
jfs
11

Pour python 3.4 et plus, vous pouvez utiliser la classe Path

from pathlib import Path


# rpd is a symbolic link
>>> Path('rdp').is_symlink()
True
>>> Path('README').is_symlink()
False

Vous devez être prudent lorsque vous utilisez la méthode is_symlink (). Il retournera True même si la cible du lien est inexistante tant que l'objet nommé est un lien symbolique. Par exemple (Linux / Unix):

ln -s ../nonexistentfile flnk

Ensuite, dans votre répertoire actuel, lancez python

>>> from pathlib import Path
>>> Path('flnk').is_symlink()
True
>>> Path('flnk').exists()
False

Le programmeur doit décider ce qu'il veut vraiment. Python 3 semble avoir renommé de nombreuses classes. Il peut être intéressant de lire la page de manuel de la classe Path: https://docs.python.org/3/library/pathlib.html

Kemin Zhou
la source
cela PEUT ne trouver qu'un lien symbolique valide, cela PEUT ne pas identifier un fichier qui est un lien symbolique mais qui est rompu. donc si vous filtrez pour des fichiers réels ou tous les liens symboliques (bons et mauvais), assurez-vous de faire des vérifications supplémentaires
2114L3
@ 2114L3 Que signifie un lien symbolique valide mais rompu? De simples tests avec un lien symbolique cassé, il semble que ce is_symlink()soit vrai et exists()faux, ce à quoi je m'attendais. Pouvez-vous donner une source pour vos préoccupations?
Jonathan H
1
@Sheljohn vérifie les modifications sur cette réponse, avant que mon commentaire n'existe () ne faisait pas partie de la réponse. utiliser existe est une vérification supplémentaire dont je parlais. car utiliser is_symlink seul ne suffit pas selon la version originale.
2114L3
Sous Windows, cela ne fonctionne pas correctement pour moi: is_symlinkretourne truepour des fichiers inexistants (donc exists()retourne également true).
James Hirschorn
3

Sans l'intention de gonfler ce sujet, mais j'ai été redirigé vers cette page car je cherchais des liens symboliques pour les trouver et les convertir en fichiers réels et j'ai trouvé ce script dans la bibliothèque d'outils python.

#Source https://github.com/python/cpython/blob/master/Tools/scripts/mkreal.py


import sys
import os
from stat import *

BUFSIZE = 32*1024

def mkrealfile(name):
    st = os.stat(name) # Get the mode
    mode = S_IMODE(st[ST_MODE])
    linkto = os.readlink(name) # Make sure again it's a symlink
    f_in = open(name, 'r') # This ensures it's a file
    os.unlink(name)
    f_out = open(name, 'w')
    while 1:
        buf = f_in.read(BUFSIZE)
        if not buf: break
        f_out.write(buf)
    del f_out # Flush data to disk before changing mode
    os.chmod(name, mode)

    mkrealfile("/Users/test/mysymlink")
user1767754
la source