用于连接点目标的Python测试

时间:2014-02-04 19:41:58

标签: python

在Windows下使用Python 2.7有没有办法检查文件夹是否是任何联结点的目标?如果是这样,找到哪个符号链接会导致它?

例如,在dos shell中使用mklink

创建一个连接点
C:\>mklink /J C:\junction C:\Users
Junction created for C:\junction <<===>> C:\Users

并且在python中(假设没有事先知道这个连接存在)测试“C:\ Users”如果它是任何连接点的目标,返回一个符号链接列表,如果为True,在这种情况下:['C: \结']

2 个答案:

答案 0 :(得分:1)

这是我使用名为Windows directory walk using ctypes的ActiveState配方中的一些代码放在一起的东西。与使用win32 FindFirstFileFindNextFile函数相比,可能有更直接的方法,但这似乎适用于我的有限测试。

import os
import sys
import ctypes
from ctypes import Structure
from ctypes import byref
import ctypes.wintypes as wintypes
from ctypes import addressof

FILE_ATTRIBUTE_DIRECTORY = 16  # (0x10)
FILE_ATTRIBUTE_REPARSE_POINT = 1024  # (0x400)
MAX_PATH = 260

GetLastError = ctypes.windll.kernel32.GetLastError

class FILETIME(Structure):
    _fields_ = [("dwLowDateTime", wintypes.DWORD),
                ("dwHighDateTime", wintypes.DWORD)]

class WIN32_FIND_DATAW(Structure):
    _fields_ = [("dwFileAttributes", wintypes.DWORD),
                ("ftCreationTime", FILETIME),
                ("ftLastAccessTime", FILETIME),
                ("ftLastWriteTime", FILETIME),
                ("nFileSizeHigh", wintypes.DWORD),
                ("nFileSizeLow", wintypes.DWORD),
                ("dwReserved0", wintypes.DWORD),
                ("dwReserved1", wintypes.DWORD),
                ("cFileName", wintypes.WCHAR * MAX_PATH),
                ("cAlternateFileName", wintypes.WCHAR * 20)]

def find_junctions(folder):
    """ Return a list of subdirectories in folder which are junction points """
    if not os.path.isdir(folder):
        return False
    folder = unicode(folder)
    if not folder.startswith(u'\\\\?\\'):
        if folder.startswith(u'\\\\'):
            # network drive
            folder = u'\\\\?\\UNC' + folder[1:]
        else:
            # local drive
            folder = u'\\\\?\\' + folder

    junction_points = []
    data = WIN32_FIND_DATAW()
    h = ctypes.windll.kernel32.FindFirstFileW(os.path.join(folder, u'*'),
                                              byref(data))
    last_error = ctypes.windll.kernel32.GetLastError()
    if h < 0:
        ctypes.windll.kernel32.FindClose(h)
        if not sys.stderr.isatty():
            print >> sys.stderr, ('Failed to find first file %s' %
                                   os.path.join(folder, u'*'))
        if last_error != 5:  # access denied.
            raise WindowsError('FindFirstFileW %s, Error: %d' %
                               (folder, ctypes.windll.kernel32.GetLastError()))
        return []

    if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY and
        data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT):
        if data.cFileName not in (u'.', u'..'):
            junction_points.append(data.cFileName[:])

    try:
        while ctypes.windll.kernel32.FindNextFileW(h, byref(data)):
            if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY and
                data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT):
                if data.cFileName not in (u'.', u'..'):
                    junction_points.append(data.cFileName[:])
    except WindowsError as e:
        if not sys.stderr.isatty():
            print >> sys.stderr, (
                'Failed to find next file %s, handle %d, buff addr: 0x%x' %
                (os.path.join(folder, u'*'), h, addressof(data)))

    ctypes.windll.kernel32.FindClose(h)
    return junction_points

def is_junction_point(folder):
    dirpath, folder = os.path.split(os.path.abspath(folder))
    return unicode(folder) in find_junctions(dirpath)

答案 1 :(得分:0)

看起来这很难有效,但您可以扫描卷上的所有现有交接点(请参阅http://en.wikipedia.org/wiki/NTFS_junction_point“获取交接点列表”)。然后,您必须将这些与实际指向的内容相关联。目录本身并不指向现有的联结,因此您可以非常有限地找到这些联结。