I use a Python script, running in a Cygwin build of Python, to create commands issued to native Windows utilities (not Cygwin-aware). This requires conversion of path parameters from POSIX to WIN form before issuing the command.
Calling the cygpath utility is the nicest way to do this, since it uses Cygwin to do what it's there to do, but it's also a little horrifying (and slow).
I'm already running a Cygwin build of Python - so the code to do the conversion is present. It seems like there should be a Cygwin/Python specific extension that gives me a hook to this capability, directly in Python, without having to fire up a whole new process.
The cygpath program is a utility that converts Windows native filenames to Cygwin POSIX-style pathnames and vice versa. It can be used when a Cygwin program needs to pass a file name to a native Windows program, or expects to get a file name from a native Windows program.
Using Cygwin As noted, Cygwin provides a Unix-like environment under Windows. The installation directory (by default, c:\cygwin) is the root of the Unix-like file system, which contains bin, etc, home, tmp, and usr directories as would be found on a GNU/Linux or other Unix system.
In a new installation of Cygwin, your home directory will be in C:/cygwin/home/<user>/ , and can be accessed by the usual ~ shortcut. Although this works just fine, it's often useful to use the utilities provided by Cygwin in your local Windows user area C:/Users/<user> .
This is possible by calling the Cygwin API using ctypes. The below code works for me–I am using 64-bit cygwin DLL version 2.5.2 on Windows 2012, and this works on the Cygwin versions of both Python 2.7.10 and Python 3.4.3.
Basically we call cygwin_create_path
from cygwin1.dll
to perform the path conversion. That function allocates a memory buffer (using malloc
) containing the converted path. So then we need to use free
from cygwin1.dll
to release the buffer it allocated.
Note that xunicode
below is a poor man's alternative to six (a Python 2/3 compatibility library); if you need to support both Python 2 and 3, six is the much better answer, but I wanted my example to be free of dependencies on any non-bundled modules which is why I did it this way.
from ctypes import cdll, c_void_p, c_int32, cast, c_char_p, c_wchar_p
from sys import version_info
xunicode = str if version_info[0] > 2 else eval("unicode")
# If running under Cygwin Python, just use DLL name
# If running under non-Cygwin Windows Python, use full path to cygwin1.dll
# Note Python and cygwin1.dll must match bitness (i.e. 32-bit Python must
# use 32-bit cygwin1.dll, 64-bit Python must use 64-bit cygwin1.dll.)
cygwin = cdll.LoadLibrary("cygwin1.dll")
cygwin_create_path = cygwin.cygwin_create_path
cygwin_create_path.restype = c_void_p
cygwin_create_path.argtypes = [c_int32, c_void_p]
# Initialise the cygwin DLL. This step should only be done if using
# non-Cygwin Python. If you are using Cygwin Python don't do this because
# it has already been done for you.
cygwin_dll_init = cygwin.cygwin_dll_init
cygwin_dll_init.restype = None
cygwin_dll_init.argtypes = []
cygwin_dll_init()
free = cygwin.free
free.restype = None
free.argtypes = [c_void_p]
CCP_POSIX_TO_WIN_A = 0
CCP_POSIX_TO_WIN_W = 1
CCP_WIN_A_TO_POSIX = 2
CCP_WIN_W_TO_POSIX = 3
def win2posix(path):
"""Convert a Windows path to a Cygwin path"""
result = cygwin_create_path(CCP_WIN_W_TO_POSIX,xunicode(path))
if result is None:
raise Exception("cygwin_create_path failed")
value = cast(result,c_char_p).value
free(result)
return value
def posix2win(path):
"""Convert a Cygwin path to a Windows path"""
result = cygwin_create_path(CCP_POSIX_TO_WIN_W,str(path))
if result is None:
raise Exception("cygwin_create_path failed")
value = cast(result,c_wchar_p).value
free(result)
return value
# Example, convert LOCALAPPDATA to cygwin path and back
from os import environ
localAppData = environ["LOCALAPPDATA"]
print("Original Win32 path: %s" % localAppData)
localAppData = win2posix(localAppData)
print("As a POSIX path: %s" % localAppData)
localAppData = posix2win(localAppData)
print("Back to a Windows path: %s" % localAppData)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With