2024-05-15 15:29:33 发布
网友
有没有办法在Python中创建NTFS连接点?我知道我可以调用junction实用程序,但最好不要依赖外部工具。
junction
您可以使用python win32 API模块,例如
import win32file win32file.CreateSymbolicLink(srcDir, targetDir, 1)
有关详细信息,请参见http://docs.activestate.com/activepython/2.5/pywin32/win32file__CreateSymbolicLink_meth.html
如果您不想依赖它,那么您可以始终使用ctypes并直接调用createSymbolClinWin32API,这无论如何都是一个简单的调用
下面是使用ctypes的调用示例
import ctypes kdll = ctypes.windll.LoadLibrary("kernel32.dll") kdll.CreateSymbolicLinkA("d:\testdir", "d:\testdir_link", 1)
MSDN表示支持的最低客户端Windows Vista
自Python 3.5以来,在_winapi模块中有一个函数CreateJunction。
_winapi
CreateJunction
import _winapi _winapi.CreateJunction(source, target)
我用similar question回答了这个问题,所以我将把我的答案复制到下面。自从编写了这个答案之后,我最终编写了一个python-only(如果您可以调用一个只使用ctypes-python的模块)模块来创建、读取和检查可以在this folder中找到的连接。希望能有所帮助。
此外,与使用CreateSymbolicLinkAAPI的答案不同,链接的实现应该在任何支持连接的Windows版本上工作。只在Vista+中支持createsymbolicinka。
回答:
python ntfslink extension
或者,如果要使用pywin32,可以使用前面声明的方法,并且要读取,请使用:
from win32file import * from winioctlcon import FSCTL_GET_REPARSE_POINT __all__ = ['islink', 'readlink'] # Win32file doesn't seem to have this attribute. FILE_ATTRIBUTE_REPARSE_POINT = 1024 # To make things easier. REPARSE_FOLDER = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT) # For the parse_reparse_buffer function SYMBOLIC_LINK = 'symbolic' MOUNTPOINT = 'mountpoint' GENERIC = 'generic' def islink(fpath): """ Windows islink implementation. """ if GetFileAttributes(fpath) & REPARSE_FOLDER: return True return False def parse_reparse_buffer(original, reparse_type=SYMBOLIC_LINK): """ Implementing the below in Python: typedef struct _REPARSE_DATA_BUFFER { ULONG ReparseTag; USHORT ReparseDataLength; USHORT Reserved; union { struct { USHORT SubstituteNameOffset; USHORT SubstituteNameLength; USHORT PrintNameOffset; USHORT PrintNameLength; ULONG Flags; WCHAR PathBuffer[1]; } SymbolicLinkReparseBuffer; struct { USHORT SubstituteNameOffset; USHORT SubstituteNameLength; USHORT PrintNameOffset; USHORT PrintNameLength; WCHAR PathBuffer[1]; } MountPointReparseBuffer; struct { UCHAR DataBuffer[1]; } GenericReparseBuffer; } DUMMYUNIONNAME; } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; """ # Size of our data types SZULONG = 4 # sizeof(ULONG) SZUSHORT = 2 # sizeof(USHORT) # Our structure. # Probably a better way to iterate a dictionary in a particular order, # but I was in a hurry, unfortunately, so I used pkeys. buffer = { 'tag' : SZULONG, 'data_length' : SZUSHORT, 'reserved' : SZUSHORT, SYMBOLIC_LINK : { 'substitute_name_offset' : SZUSHORT, 'substitute_name_length' : SZUSHORT, 'print_name_offset' : SZUSHORT, 'print_name_length' : SZUSHORT, 'flags' : SZULONG, 'buffer' : u'', 'pkeys' : [ 'substitute_name_offset', 'substitute_name_length', 'print_name_offset', 'print_name_length', 'flags', ] }, MOUNTPOINT : { 'substitute_name_offset' : SZUSHORT, 'substitute_name_length' : SZUSHORT, 'print_name_offset' : SZUSHORT, 'print_name_length' : SZUSHORT, 'buffer' : u'', 'pkeys' : [ 'substitute_name_offset', 'substitute_name_length', 'print_name_offset', 'print_name_length', ] }, GENERIC : { 'pkeys' : [], 'buffer': '' } } # Header stuff buffer['tag'] = original[:SZULONG] buffer['data_length'] = original[SZULONG:SZUSHORT] buffer['reserved'] = original[SZULONG+SZUSHORT:SZUSHORT] original = original[8:] # Parsing k = reparse_type for c in buffer[k]['pkeys']: if type(buffer[k][c]) == int: sz = buffer[k][c] bytes = original[:sz] buffer[k][c] = 0 for b in bytes: n = ord(b) if n: buffer[k][c] += n original = original[sz:] # Using the offset and length's grabbed, we'll set the buffer. buffer[k]['buffer'] = original return buffer def readlink(fpath): """ Windows readlink implementation. """ # This wouldn't return true if the file didn't exist, as far as I know. if not islink(fpath): return None # Open the file correctly depending on the string type. handle = CreateFileW(fpath, GENERIC_READ, 0, None, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, 0) \ if type(fpath) == unicode else \ CreateFile(fpath, GENERIC_READ, 0, None, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, 0) # MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16384 = (16*1024) buffer = DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, None, 16*1024) # Above will return an ugly string (byte array), so we'll need to parse it. # But first, we'll close the handle to our file so we're not locking it anymore. CloseHandle(handle) # Minimum possible length (assuming that the length of the target is bigger than 0) if len(buffer) < 9: return None # Parse and return our result. result = parse_reparse_buffer(buffer) offset = result[SYMBOLIC_LINK]['substitute_name_offset'] ending = offset + result[SYMBOLIC_LINK]['substitute_name_length'] rpath = result[SYMBOLIC_LINK]['buffer'][offset:ending].replace('\x00','') if len(rpath) > 4 and rpath[0:4] == '\\??\\': rpath = rpath[4:] return rpath def realpath(fpath): from os import path while islink(fpath): rpath = readlink(fpath) if not path.isabs(rpath): rpath = path.abspath(path.join(path.dirname(fpath), rpath)) fpath = rpath return fpath def example(): from os import system, unlink system('cmd.exe /c echo Hello World > test.txt') system('mklink test-link.txt test.txt') print 'IsLink: %s' % islink('test-link.txt') print 'ReadLink: %s' % readlink('test-link.txt') print 'RealPath: %s' % realpath('test-link.txt') unlink('test-link.txt') unlink('test.txt') if __name__=='__main__': example()
根据需要调整CreateFile中的属性,但对于正常情况,它应该可以工作。请随意改进。
如果使用MOUNTPOINT而不是符号链接,则它也应该适用于文件夹连接。
你可以检查一下
sys.getwindowsversion()[0] >= 6
如果你把这个放到你要发布的东西中,因为这种形式的符号链接只在Vista+上支持。
您可以使用python win32 API模块,例如
有关详细信息,请参见http://docs.activestate.com/activepython/2.5/pywin32/win32file__CreateSymbolicLink_meth.html
如果您不想依赖它,那么您可以始终使用ctypes并直接调用createSymbolClinWin32API,这无论如何都是一个简单的调用
下面是使用ctypes的调用示例
MSDN表示支持的最低客户端Windows Vista
自Python 3.5以来,在
_winapi
模块中有一个函数CreateJunction
。我用similar question回答了这个问题,所以我将把我的答案复制到下面。自从编写了这个答案之后,我最终编写了一个python-only(如果您可以调用一个只使用ctypes-python的模块)模块来创建、读取和检查可以在this folder中找到的连接。希望能有所帮助。
此外,与使用CreateSymbolicLinkAAPI的答案不同,链接的实现应该在任何支持连接的Windows版本上工作。只在Vista+中支持createsymbolicinka。
回答:
python ntfslink extension
或者,如果要使用pywin32,可以使用前面声明的方法,并且要读取,请使用:
根据需要调整CreateFile中的属性,但对于正常情况,它应该可以工作。请随意改进。
如果使用MOUNTPOINT而不是符号链接,则它也应该适用于文件夹连接。
你可以检查一下
如果你把这个放到你要发布的东西中,因为这种形式的符号链接只在Vista+上支持。
相关问题 更多 >
编程相关推荐