C'è un modo per creare un punto di giunzione NTFS in Python? So che posso chiamare l'utilità junction
, ma sarebbe meglio non fare affidamento su strumenti esterni.Creare il punto di giunzione NTFS in Python
risposta
Ho risposto a questo in un similar question, quindi copierò la mia risposta a quella di seguito. Da quando ho scritto quella risposta, ho finito per scrivere un modulo solo per Python (se puoi chiamare un modulo che usa solo ctype python) per creare, leggere e controllare i junctions che possono essere trovati in this folder. Spero possa aiutare.
Inoltre, a differenza della risposta che utilizza l'API CreateSymbolicLinkA, l'implementazione collegata dovrebbe funzionare su qualsiasi versione di Windows che supporti i junction. CreateSymbolicLinkA è supportato solo in Vista +.
Risposta:
Oppure, se si desidera utilizzare pywin32, è possibile utilizzare il metodo affermato in precedenza, e di leggere, uso:
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()
Regolare gli attributi CreateFile alle tue esigenze, ma per una situazione normale, dovrebbe funzionare. Sentiti libero di migliorare.
Dovrebbe funzionare anche per i raccoglitori di cartelle se si utilizza MOUNTPOINT anziché SYMBOLIC_LINK.
'possibile modo per verificare che
sys.getwindowsversion()[0] >= 6
se si mette questo in qualcosa si sta liberando, dal momento che questa forma di link simbolico è supportato solo su Vista +.
Non si vuole fare affidamento su strumenti esterni, ma non ti importa fare affidamento sull'ambiente specifico? Penso che si possa tranquillamente supporre che, se si tratta di NTFS su cui si sta lavorando, l'utilità di junction sarà probabilmente presente.
Ma, se vuoi dire che preferiresti non chiamare un programma esterno, ho trovato che il materiale ctypes ha un valore inestimabile. Permette di chiamare DLL Windows direttamente da Python. E sono abbastanza sicuro che sia nelle versioni standard di Python al giorno d'oggi.
Dovresti solo capire quale DLL di Windows è la chiamata all'API CreateJunction()
(o qualsiasi altra chiavetta di Windows) e imposta i parametri e chiama. Buona fortuna, Microsoft non sembra supportarla molto bene. È potrebbe smontare il programma SysInternals junction
o linkd
o uno degli altri strumenti per scoprire come lo fanno.
Me, io sono abbastanza pigro, mi basta chiamare junction
come un processo esterno :-)
ctypes è incluso in Python dalla versione 2.5 in poi. –
Il comando di giunzione non esiste su Vista e Win7. È stato sostituito da mklink. –
Esiste come una giunzione di strumento Sysinternals. – Nux
è possibile utilizzare moduli Python API Win32 per esempio
import win32file
win32file.CreateSymbolicLink(srcDir, targetDir, 1)
vedere http://docs.activestate.com/activepython/2.5/pywin32/win32file__CreateSymbolicLink_meth.html per maggiori dettagli
se non si vuole fare affidamento anche su questo, si può sempre usare ctypes e chiamare direttamente CreateSymbolicLinl Win32 API, che è in ogni caso una semplice chiamata
qui è esempio chiamata utilizzando ctypes
import ctypes
kdll = ctypes.windll.LoadLibrary("kernel32.dll")
kdll.CreateSymbolicLinkA("d:\testdir", "d:\testdir_link", 1)
MSDN dice minima supportata client Windows Vista
012.Penso che le giunzioni fossero da Win2K in poi ma non ufficialmente (o bene) sostenuta dagli Stati membri, vista la scarsità di documenti su come farlo. I nuovi collegamenti simbolici sono molto più interessanti, soprattutto perché puoi applicarli ai file e (credo) che ora possono attraversare le reti. – paxdiablo
yes junctions sono sottoinsieme di collegamenti simbolici –
Le giunzioni sono _non_ un sottoinsieme di collegamenti simbolici. Le giunzioni si applicano solo alle directory. Questa risposta non è corretta e crea un collegamento simbolico per i file (che funziona solo su Vista e sopra) piuttosto che un bivio per le directory (che funziona su NTFS in Windows 2000) e sopra. Sfortunatamente, non esiste un vero e semplice modo per farlo in Python. –
Da Python 3.5 esiste una funzione CreateJunction
nel modulo _winapi
.
import _winapi
_winapi.CreateJunction(source, target)
- 1. In .NET, come si crea una giunzione in NTFS, al contrario di un collegamento simbolico?
- 2. Qual è la differenza tra punti di giunzione NTFS e collegamenti simbolici?
- 3. Ruota il punto su un altro punto in gradi python
- 4. Controllo di permessi ntfs per cartelle/file usando python
- 5. Come creare un punto di congiunzione con WinApi?
- 6. Qual è la differenza tra giunzione interna e giunzione esterna
- 7. Modifica diario per blocchi in Windows (NTFS)
- 8. Qual è il punto di float ('Inf') in Python?
- 9. RAII in Python: qual è il punto di __del__?
- 10. L'implementazione di un sistema di giunzione "configurabile", in modo sicuro
- 11. Esistono limiti di lunghezza del percorso del file in NTFS?
- 12. Grafico da python a punto
- 13. Array giunzione genera un errore in IE
- 14. Cartella Temp di Windows predefinita Protezione NTFS
- 15. Mercurial e NTFS flusso di dati alternativo
- 16. Esiste una funzione integrata come la giunzione di Perl in Python?
- 17. Alternativa non distruttiva alla giunzione?
- 18. sostituisce il punto e virgola con newline in python code
- 19. Il punto e virgola di Python fa la differenza
- 20. Python: verifica se il punto è all'interno di un poligono
- 21. Hibernate NOT IN sottoquery sulla tabella di giunzione
- 22. powershell per risolvere il percorso target della giunzione
- 23. Il modo più veloce per trovare il punto più vicino a un punto specifico in 3D, in Python
- 24. Autorizzazioni ereditate perse con autorizzazioni NTFS
- 25. Qual è il punto di os.error?
- 26. Come collegare ntfs-3g con homebrew?
- 27. Come si esegue una query su una tabella di giunzione
- 28. Tabelle di giunzione rispetto a matrici di chiavi esterne?
- 29. Come creare un'ontologia in python?
- 30. Reagire-DND quello che fa $ giunzione non
Si noti che l'estensione ntfslink è attualmente danneggiata in Python3 – CharlesB
Vedere la mia risposta qui sotto per Python> = 3.5 – CharlesB