누구나 파이썬에서 win32 버전의 심볼릭 링크를 만들고 읽는 방법을 알고 있습니까? 이상적으로는 플랫폼 별 코드가 최소한 있어야합니다. 앱을 크로스 플랫폼으로 사용해야합니다.Windows의 심볼릭 링크?
답변
문제는 설명 된대로입니다. here, 심볼 링크의 기능에 대한 Windows의 자체 지원은 Windows 릴리스마다 다르므로 예를 들어. 비스타에서는 (많은 작업을 통해) XP 나 2000보다 더 많은 기능을 사용할 수 있습니다 (다른 win32 버전에서는 AFAIK가 없습니다). 또는 대신 단축키를 사용할 수 있습니다. 물론 단축키는 고유 한 제한 집합을 가지고 있으며 실제로는 유닉스 심볼 링크와 동등하지 않습니다. 따라서, 여러분이 요구하는 기능을 정확하게 지정해야하며, cross-win32 작업의 제단에서 희생하고자하는 것들 중 얼마만큼을 지정해야합니다. 그런 다음, 우리는 여러분이 선택한 절충안을 어떻게 구현할 것인지를 결정할 수 있습니다 ctypes
또는 win32all
이 호출됩니다. 그 의미는 가장 적습니다.
NTFS 파일 시스템에 연결점이 있으므로 대신 사용할 수 있다고 생각합니다. 예를 들어 Python Win32 API 모듈을 사용할 수 있습니다. 예 : 당신이 win32API 모듈에 의존하지 않으려면
import win32file
win32file.CreateSymbolicLink(fileSrc, fileTarget, 1)
, 당신은 항상 ctypes
를 사용하여 직접, 예를 들어 CreateSymbolicLink
는 Win32 API를 호출 할 수 있습니다
import ctypes
kdll = ctypes.windll.LoadLibrary("kernel32.dll")
kdll.CreateSymbolicLinkA("d:\\test.txt", "d:\\test_link.txt", 0)
MSDN (http://msdn.microsoft.com/en-us/library/aa363866(VS.85).aspx가) 최소 클라이언트가 윈도우 비스타 또한에서
지원 말한다 :이 또한 디렉토리와 함께 작동 (그 세 번째 인수로 표시). 유니 코드 지원으로는 다음과 같습니다
이kdll.CreateSymbolicLinkW(UR"D:\testdirLink", UR"D:\testdir", 1)
또한 내가 lib 디렉토리/사이트 패키지/sitecustomize.py에 다음을 넣어 Create NTFS junction point in Python
당신은'..A' Windows API를 사용해서는 안되며 매번'..W' (유니 코드)를 사용하십시오. – sorin
유니 코드를 사용하여 디렉토리 링크의 예제를 추가했습니다. –
'win32file.CreateSymbolicLink'에 표시된 매개 변수 이름은 다소 혼란 스럽습니다. 궁금한 사람들을 위해, 첫 번째는 만들 링크의 이름이고, 두 번째는 링크해야 할 경로입니다. – brianmearns
를 참조
import os
__CSL = None
def symlink(source, link_name):
'''symlink(source, link_name)
Creates a symbolic link pointing to source named link_name'''
global __CSL
if __CSL is None:
import ctypes
csl = ctypes.windll.kernel32.CreateSymbolicLinkW
csl.argtypes = (ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32)
csl.restype = ctypes.c_ubyte
__CSL = csl
flags = 0
if source is not None and os.path.isdir(source):
flags = 1
if __CSL(link_name, source, flags) == 0:
raise ctypes.WinError()
os.symlink = symlink
또는 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 == 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의 특성을 필요에 맞게 조정하지만 정상적인 경우에는 정상적으로 작동합니다. 기분 전환하십시오.
SYMBOLIC_LINK 대신 MOUNTPOINT를 사용하면 폴더 접합에도 사용할 수 있습니다.
당신은 방법은이 심볼릭 링크의 형태로 있기 때문에, 당신은 해제하고 뭔가에 유입되면sys.getwindowsversion()[0] >= 6
은 비스타 +에서 지원되는지 확인 할 수 있습니다.
수정 사항을 제출했지만 실제로 버그가 있음에도 불구하고 거부되었습니다. islink()에서 가면 값은 가양 성을 피하기 위해 마스크와 비교되어야합니다 (0 = false/nonzero = true 단축키는 단일 비트 마스크 (예 : 1024)에서만 사용됨). 그렇지 않으면 정상적인 dirs는 "링크"로 식별됩니다. "GetFileAttributes (fpath) & REPARSE_FOLDER == REPARSE_FOLDER : – MartyMacGyver
만약 내가 그것을 거절했다면, 나는 틀림없이 그렇게했을 것입니다. 나는 그것에 대해 미안합니다. (솔직히, 나는 편집 요구를 보러 갈 곳이 어디인지 모르겠다. 나는 여기에 하나도받지 못했다.) 나는 앞서 가서 수정하여 업데이트했지만, 그렇게 해 주셔서 감사합니다. –
아뇨, * 당신이 아무 것도 거절하지 않았습니다 ... 다른 두 편집자가했는데, 제 제안 된 편집이 단순히 버그를 바로 잡았 기 때문에 특이했습니다. 즉, 귀하의 게시물에 다시 한 번 감사드립니다. :-) – MartyMacGyver
Juntalis의 코드는 유니 코드를 처리하지 않으므로 ctypes를 사용하도록 수정했으며 struct를 사용하여 단순화했습니다. 나는 또한 NTFS 파일 시스템에서 Windows 8.1을 사용하여 파이썬 3.3에서 작동 os.symlink Using a struct as a function argument with the python ctypes module
import os, ctypes, struct
from ctypes import windll, wintypes
FSCTL_GET_REPARSE_POINT = 0x900a8
FILE_ATTRIBUTE_READONLY = 0x0001
FILE_ATTRIBUTE_HIDDEN = 0x0002
FILE_ATTRIBUTE_DIRECTORY = 0x0010
FILE_ATTRIBUTE_NORMAL = 0x0080
FILE_ATTRIBUTE_REPARSE_POINT = 0x0400
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
OPEN_EXISTING = 3
FILE_READ_ATTRIBUTES = 0x80
FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000
INVALID_HANDLE_VALUE = wintypes.HANDLE(-1).value
INVALID_FILE_ATTRIBUTES = 0xFFFFFFFF
FILE_FLAG_OPEN_REPARSE_POINT = 2097152
FILE_FLAG_BACKUP_SEMANTICS = 33554432
# FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTI
FILE_FLAG_REPARSE_BACKUP = 35651584
GetFileAttributes = windll.kernel32.GetFileAttributesW
_CreateFileW = windll.kernel32.CreateFileW
_DevIoCtl = windll.kernel32.DeviceIoControl
_DevIoCtl.argtypes = [
wintypes.HANDLE, #HANDLE hDevice
wintypes.DWORD, #DWORD dwIoControlCode
wintypes.LPVOID, #LPVOID lpInBuffer
wintypes.DWORD, #DWORD nInBufferSize
wintypes.LPVOID, #LPVOID lpOutBuffer
wintypes.DWORD, #DWORD nOutBufferSize
ctypes.POINTER(wintypes.DWORD), #LPDWORD lpBytesReturned
wintypes.LPVOID] #LPOVERLAPPED lpOverlapped
_DevIoCtl.restype = wintypes.BOOL
def islink(path):
assert os.path.isdir(path), path
if GetFileAttributes(path) & FILE_ATTRIBUTE_REPARSE_POINT:
return True
else:
return False
def DeviceIoControl(hDevice, ioControlCode, input, output):
# DeviceIoControl Function
# http://msdn.microsoft.com/en-us/library/aa363216(v=vs.85).aspx
if input:
input_size = len(input)
else:
input_size = 0
if isinstance(output, int):
output = ctypes.create_string_buffer(output)
output_size = len(output)
assert isinstance(output, ctypes.Array)
bytesReturned = wintypes.DWORD()
status = _DevIoCtl(hDevice, ioControlCode, input,
input_size, output, output_size, bytesReturned, None)
print "status(%d)" % status
if status != 0:
return output[:bytesReturned.value]
else:
return None
def CreateFile(path, access, sharemode, creation, flags):
return _CreateFileW(path, access, sharemode, None, creation, flags, None)
SymbolicLinkReparseFormat = "LHHHHHHL"
SymbolicLinkReparseSize = struct.calcsize(SymbolicLinkReparseFormat);
def readlink(path):
""" Windows readlink implementation. """
# This wouldn't return true if the file didn't exist, as far as I know.
assert islink(path)
assert type(path) == unicode
# Open the file correctly depending on the string type.
hfile = CreateFile(path, GENERIC_READ, 0, OPEN_EXISTING,
FILE_FLAG_REPARSE_BACKUP)
# MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16384 = (16*1024)
buffer = DeviceIoControl(hfile, FSCTL_GET_REPARSE_POINT, None, 16384)
CloseHandle(hfile)
# Minimum possible length (assuming length of the target is bigger than 0)
if not buffer or len(buffer) < 9:
return None
# Parse and return our result.
# 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;
# Only handle SymbolicLinkReparseBuffer
(tag, dataLength, reserver, SubstituteNameOffset, SubstituteNameLength,
PrintNameOffset, PrintNameLength,
Flags) = struct.unpack(SymbolicLinkReparseFormat,
buffer[:SymbolicLinkReparseSize])
print tag, dataLength, reserver, SubstituteNameOffset, SubstituteNameLength
start = SubstituteNameOffset + SymbolicLinkReparseSize
actualPath = buffer[start : start + SubstituteNameLength].decode("utf-16")
# This utf-16 string is null terminated
index = actualPath.find(u"\0")
assert index > 0
if index > 0:
actualPath = actualPath[:index]
if actualPath.startswith(u"?\\"):
return actualPath[2:]
else:
return actualPath
그래, 재 파일 포인트가 유니 코드 문자열로 저장되었다는 것을 깨닫지 못했다. (어리석은 실수) 위의 코드 나 방금 최근에 발견 한 모듈 (https://github.com/sid0/ntfs)을 사용하는 것이 훨씬 낫습니다. –
에서 코드를 협의했습니다.
여기에 내가 윈도우 XP SP3을에 CreateHardLinkA을 사용 http://www.geoffchappell.com/studies/windows/win32/kernel32/api/
KERNEL32.DLL
의 모든 메소드를 포함하는 링크, 그것은했다!
수입하는 ctypes os.path.exists (link_file) 경우 : os.remove (link_file)
dll = ctypes.windll.LoadLibrary("kernel32.dll")
dll.CreateHardLinkA(link_file, _log_filename, 0)
Vista에서 소개 된 Symlink는 재분석 지점으로 구현되므로 POSIX의 심볼릭 링크와 가깝습니다. 하드 링크는 그 일과 관련이 없습니다. – 0xC0000022L
링크를 생성 서브 프로세스에 mklink 명령을 사용하여.
from subprocess import call
call(['mklink', 'LINK', 'TARGET'], shell=True)
다른 솔루션에 문제가 있습니다.하지만 제대로 작동합니다. – Zitrax
- 1. Windows의 심볼릭 링크
- 2. android : 심볼릭 링크 결정
- 3. 파이썬에서 심볼릭 링크 복사하기
- 4. 심볼릭 링크 된 Rsync
- 5. Kohana의보기에 대한 심볼릭 링크
- 6. 심볼릭 링크 문제
- 7. 카피스트라의 심볼릭 링크 문제?
- 8. 심포니 심볼릭 링크 문제
- 9. 서버에 심볼릭 링크 업로드하기
- 10. Windows에서의 심미안 심볼릭 링크
- 11. 심볼릭 링크 확인
- 12. 심볼릭 링크 한도 - Windows
- 13. TortoiseSVN을 심볼릭 링크
- 14. Windows의 하드 링크 xp
- 15. 네트워크를 통한 심볼릭 링크 복사
- 16. 심볼릭 링크 - 대소 문자 민감도
- 17. 파이썬과의 잘못된 심볼릭 링크 찾기
- 18. 비트 버킷에 대한 심볼릭 링크
- 19. 심볼릭 링크 나열에 도움이 필요합니다.
- 20. 서브 폴더가있는 Tomcat 심볼릭 링크
- 21. rpmbuild를 통한 심볼릭 링크 패키징?
- 22. perl 심볼릭 링크 된 경로
- 23. TYPO3 확장 및 심볼릭 링크
- 24. 프로그램에 대한 심볼릭 링크 생성
- 25. Windows의 Apache 가상 호스트 - 심볼릭 링크를 어떻게 처리합니까?
- 26. 내가 심볼릭 링크를 생성 한 심볼릭 링크 레드햇을 리눅스
- 27. Windows에서 잘못된 심볼릭 링크 찾기 및 삭제
- 28. 가상 파일 시스템에서 심볼릭 링크 구현
- 29. NTFS 접합점과 심볼릭 링크 (디렉토리 용)
- 30. 자바 코드 컴파일을위한 라이브러리에 대한 심볼릭 링크
내가 필요로하는 기능은 파일 시스템의 서로 다른 장소에서 파일에 대한 링크를 포함하는 디렉토리를 만든 다음 그들이 그 디렉토리에있는 것처럼 내 파이썬 코드가 해당 파일을 열 수있을 수있을 것입니다. –
왜 그 기능이 필요합니까? –