2013-03-06 6 views
11

Unter Windows 7 mit Python 2.7 wie kann ich feststellen, ob ein Pfad eine symbolische Verbindung ist? Das funktioniert nicht , es sagt, es gibt false zurück, wenn falsch oder nicht unterstützt und der Pfad, den ich zur Verfügung stelle, ist definitiv ein symbolischer Link, also nehme ich an, dass es nicht unter Windows unterstützt wird? Was kann ich tun?os.path.islink unter Windows mit Python

+3

[Dies] (http://bugs.python.org/issue13143) können provid e etwas Hilfe. – crayzeewulf

+2

werfen Sie einen Blick auf das ['jaraco.windows'-Paket] (https://bitbucket.org/jaraco/jaraco.windows/src/default/jaraco/windows/filesystem/__init__.py); es muss 'ctypes' verwenden, um dies zu unterstützen. Python 3.2 * unterstützt Windows Symlinks richtig. –

Antwort

19

Das Grundproblem ist, dass Sie eine zu alte Version von Python verwenden. Wenn Sie bei 2.x bleiben möchten, können Sie die neuen Funktionen, die nach Anfang 2010 hinzugefügt wurden, nicht mehr nutzen.

Eines dieser Features behandelt NTFS-Symlinks. Diese Funktionalität in 3.2 Ende 2010 aufgenommen (siehe 3.2, 3.1 und 2.7 Quelle für weitere Details.)

Den Grund Python nicht NTFS Symlinks behandeln, bevor dann ist, dass es bis Ende 2009 keine solche Sache war. (IIRC, Support war im 6.0 Kernel enthalten, aber Userland-Support erfordert ein Service Pack für Vista/2008; nur 7/2008R2 und neuer wird mit eingebaut. Zusätzlich benötigen Sie ein neues MSVCRT, um darauf zugreifen zu können Userland-Unterstützung, und Python hat eine explizite Richtlinie nicht auf neue Visual Studio-Versionen innerhalb einer Nebenversion zu aktualisieren.)

Der Grund, dass der Code nicht zurück zu 2.x portiert wurde, ist that there will never be a 2.8, und Fehlerkorrekturen wie 2.7. 3 (oder 2.7.4) bekomme keine ne w Funktionen, nur Bugfixes.

Dies wurde als issue 13143 gemeldet, und die beabsichtigte Lösung besteht darin, die 2.7 Dokumente zu ändern, um zu verdeutlichen, dass islink unter Windows immer False zurückgibt.

Also, wenn Sie NTFS symbolische Links unter Windows lesen möchten, entweder ein Upgrade auf Python 3.2 +, oder Sie haben win32api zu verwenden, ctypes usw., es selbst zu tun.

Oder, wie Martijn Pieters vorschlägt, anstatt es selbst zu tun, verwenden Sie eine Drittanbieter-Bibliothek wie jaraco.windows, die es tut und/oder leihen their code.

Oder, wenn Sie wirklich wollen, leihen Sie den Code aus der 3.2-Quelle und bauen Sie ein C-Erweiterungsmodul um es. Wenn Sie von ntpath bis os bis nt verfolgen (was eigentlich posixmodule.c ist), glaube ich, dass die Eingeweide davon in win32_xstat_impl and win32_xstat_impl_w sind.

+0

Wer downvoted, kümmern sich darum, warum zu erklären? – abarnert

+0

erstaunlich! danke abarnert – user391986

+0

Sie müssen falsch informiert werden. Analysepunkte existieren von Windows NT 5 (Windows 2000) mit NTFS 3.0. Und es war funktional. Python-Implementierung ist einfach faul oder auch falsch informiert. –

5

Dies ist, was ich, wenn eine Datei oder ein Verzeichnis zu bestimmen, indem am Ende einen Link in Windows 7:

def isLink(path): 
    if os.path.exists(path): 
     if os.path.isdir(path): 
      FILE_ATTRIBUTE_REPARSE_POINT = 0x0400 
      attributes = ctypes.windll.kernel32.GetFileAttributesW(unicode(path)) 
      return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) > 0 
     else: 
      command = ['dir', path] 
      try: 
       with open(os.devnull, 'w') as NULL_FILE: 
        o0 = check_output(command, stderr=NULL_FILE, shell=True) 
      except CalledProcessError as e: 
       print e.output 
       return False 
      o1 = [s.strip() for s in o0.split('\n')] 
      if len(o1) < 6: 
       return False 
      else: 
       return 'SYMLINK' in o1[5] 
    else: 
     return False 

EDIT: Modifizierte Code per Vorschläge von Zitrax und Annan

+0

Es lohnt sich, 'CalledProcessError' von' check_output' abzufangen, wenn die Datei nicht existiert. Sie können auch 'stderr = subprocess.PIPE' übergeben, um die Fehlerausgabe in stdin zu verbergen. Diese Lösung ist wirklich hacky, aber praktikabler als die andere Antwort. – Annan

+0

Diese Antwort funktioniert nicht, um zu prüfen, ob ein Verzeichnis ein Link ist, denn der Befehl dir listet nur den Inhalt auf. – Zitrax

+0

@Zitrax: 'dir/al" path * "' funktioniert –

5

Für Verzeichnisse :

import os, ctypes 
def IsSymlink(path): 
    FILE_ATTRIBUTE_REPARSE_POINT = 0x0400 
    return os.path.isdir(path) and (ctypes.windll.kernel32.GetFileAttributesW(unicode(path)) & FILE_ATTRIBUTE_REPARSE_POINT): 

Source

+0

die Quelle ist tot – thatsIch

+0

@thatsIch aktualisiert Link zu Archiv-Cache. – Zitrax

+0

Beim Vergleichen der Quelle fehlt die Rückgabeanweisung. Sie können prüfen, ob das Ergebnis> 0 ist, andernfalls ist das Ergebnis 1024 – thatsIch