Überprüfen Sie, ob die Datei in Python symlink ist

91

Gibt es in Python eine Funktion, mit der überprüft werden kann, ob eine bestimmte Datei / ein bestimmtes Verzeichnis ein Symlink ist? Für die folgenden Dateien sollte beispielsweise meine Wrapper-Funktion zurückgegeben werden 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
quelle

Antworten:

136

Verwenden Sie Folgendes, um festzustellen, ob ein Verzeichniseintrag ein Symlink ist:

os.path.islink (Pfad)

Rückgabe True, wenn der Pfad auf einen Verzeichniseintrag verweist, der eine symbolische Verknüpfung darstellt. Immer falsch, wenn symbolische Links nicht unterstützt werden.

Zum Beispiel gegeben:

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
quelle
7
Unter Windows werden Verknüpfungen als Dateien mit Erweiterung angezeigtlnk und os.islink('a_shortcut.lnk')zurückgegeben False.
Evgeni Sergeev
1
@EvgeniSergeev Das liegt daran, dass es sich nur um Dateien handelt - möglicherweise ein Kater von Windows 9x Tagen, als das einzige Dateisystem FAT / FAT32 war. Unter superuser.com/questions/347930/… finden Sie alle Arten von symbolischen / festen Links und Verzeichnisverbindungen, die von NTFS unterstützt werden. Trotzdem glaube ich immer noch nicht, dass Python sie unterstützt.
JMC
9
Und islink () funktioniert nicht für Windows-Symlinks, dh Junctions. Die Antwort gilt also nur für Unix.
Der Pate
2
Weitere Informationen finden Sie in dieser Antwort zu stackoverflow.com/questions/27972776/… , wenn Sie eine Windows-Lösung benötigen.
Der Pate
1
@TheGodfather: Directory Junction ist kein Symlink ( IO_REPARSE_TAG_SYMLINK).
JFS
10

Für Python 3.4 und höher können Sie die Path-Klasse verwenden

from pathlib import Path


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

Sie müssen vorsichtig sein, wenn Sie die Methode is_symlink () verwenden. Es wird True zurückgegeben, auch wenn das Ziel des Links nicht vorhanden ist, solange das genannte Objekt ein Symlink ist. Zum Beispiel (Linux / Unix):

ln -s ../nonexistentfile flnk

Starten Sie dann in Ihrem aktuellen Verzeichnis Python

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

Der Programmierer muss entscheiden, was er wirklich will. Python 3 scheint viele Klassen umbenannt zu haben. Es kann sich lohnen, die Handbuchseite für die Path-Klasse zu lesen: https://docs.python.org/3/library/pathlib.html

Kemin Zhou
quelle
Dies kann nur einen gültigen Symlink finden. Dies kann keine Datei identifizieren, die ein Symlink ist, aber beschädigt ist. Wenn Sie also nach echten Dateien oder allen Symlinks (gut und schlecht) filtern, stellen Sie sicher, dass Sie zusätzliche Überprüfungen durchführen
2114L3
@ 2114L3 Was bedeutet ein gültiger, aber fehlerhafter Symlink? Aus einfachen Tests mit einem defekten Symlink geht hervor, dass dies is_symlink()wahr und exists()falsch ist, was ich erwarten würde. Können Sie eine Quelle für Ihre Bedenken angeben?
Jonathan H
1
@Sheljohn überprüfe die Änderungen an dieser Antwort, bevor mein Kommentar existiert () war nicht Teil der Antwort. Die Verwendung von Exists ist eine zusätzliche Überprüfung, die ich gemeint habe. Die Verwendung von is_symlink allein reicht laut Originalversion nicht aus.
2114L3
Unter Windows funktioniert dies bei mir nicht richtig: is_symlinkGibt truefür nicht vorhandene Dateien zurück ( exists()kehrt also auch zurück true).
James Hirschorn
3

Ohne die Absicht, dieses Thema aufzublähen, wurde ich auf diese Seite weitergeleitet, als ich nach Symlinks suchte, um sie zu finden und in echte Dateien zu konvertieren, und fand dieses Skript in der Python-Tools-Bibliothek.

#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
quelle