Controlla se il file è un collegamento simbolico in Python


91

In Python, esiste una funzione per verificare se un determinato file / directory è un collegamento simbolico? Ad esempio, per i file seguenti, la mia funzione wrapper dovrebbe tornare 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

Risposte:


136

Per determinare se una voce di directory è un collegamento simbolico, usa questo:

os.path.islink (percorso)

Restituisce True se il percorso fa riferimento a una voce di directory che è un collegamento simbolico. Sempre Falso se i collegamenti simbolici non sono supportati.

Ad esempio, dato:

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

7
Su Windows, i collegamenti vengono visualizzati come file con estensione lnke os.islink('a_shortcut.lnk')restituisce False.
Evgeni Sergeev

1
@EvgeniSergeev Questo perché sono solo file - forse una sbornia da Windows 9x giorni in cui l'unico file system era FAT / FAT32. Vedere questo superuser.com/questions/347930/… per tutti i tipi di collegamenti simbolici / fisici e giunzioni di directory supportati su NTFS. Detto questo, continuo a non pensare che Python li supporti.
jmc

9
E islink () non funziona per i collegamenti simbolici di Windows, cioè le giunzioni. Quindi la risposta è applicabile solo per Unix.
Il Padrino

2
Fare riferimento a questa risposta stackoverflow.com/questions/27972776/… se è necessaria una soluzione Windows.
Il Padrino

1
@TheGodfather: directory junction non è un collegamento simbolico ( IO_REPARSE_TAG_SYMLINK).
jfs

11

Per python 3.4 e versioni successive, puoi usare la classe Path

from pathlib import Path


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

Devi stare attento quando usi il metodo is_symlink (). Restituirà True anche se la destinazione del collegamento è inesistente fintanto che l'oggetto denominato è un collegamento simbolico. Ad esempio (Linux / Unix):

ln -s ../nonexistentfile flnk

Quindi, nella directory corrente, avvia python

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

Il programmatore deve decidere cosa vuole veramente. Python 3 sembra aver rinominato molte classi. Potrebbe valere la pena leggere la pagina di manuale per la classe Path: https://docs.python.org/3/library/pathlib.html


questo MAGGIO trova solo un collegamento simbolico valido, questo POTREBBE non identificare un file che è un collegamento simbolico ma è rotto. quindi se stai filtrando per file reali o tutti i link simbolici (buoni e cattivi), assicurati di eseguire controlli aggiuntivi
2114L3

@ 2114L3 Cosa significa un collegamento simbolico valido ma non funzionante? Da un semplice test con un collegamento simbolico rotto, sembra che is_symlink()sia vero e exists()falso, che è quello che mi aspetterei. Puoi dare una fonte per le tue preoccupazioni?
Jonathan H

1
@Sheljohn controlla le modifiche a questa risposta, prima che il mio commento esista () non faceva parte della risposta. L'uso di esiste è un ulteriore controllo di cui intendevo. poiché l'uso di is_symlink da solo non è sufficiente come nella versione originale.
2114L3

Su Windows questo non funziona correttamente per me: is_symlinksta tornando trueper file inesistenti (quindi exists()restituisce anche true).
James Hirschorn

3

Senza l'intenzione di gonfiare questo argomento, ma sono stato reindirizzato a questa pagina perché stavo cercando collegamenti simbolici per trovarli e convertirli in file reali e ho trovato questo script all'interno della libreria degli strumenti 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")
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.