0

In windows, I try to get short path (8.3 dos style) of path that contains non-English chars. The following code (from here) return error in the _GetShortPathNameW() function (error is: "file not found").

# -*- coding: utf-8 -*-
import ctypes
from ctypes import wintypes

_GetShortPathNameW = ctypes.windll.kernel32.GetShortPathNameW
_GetShortPathNameW.argtypes = [wintypes.LPCWSTR, wintypes.LPWSTR, wintypes.DWORD]
_GetShortPathNameW.restype = wintypes.DWORD

def get_short_path_name(long_name):
    """
    Gets the short path name of a given long path.
    http://stackoverflow.com/a/23598461/200291
    """
    output_buf_size = 0
    while True:
        output_buf = ctypes.create_unicode_buffer(output_buf_size)
        needed = _GetShortPathNameW(long_name, output_buf, output_buf_size)
        if output_buf_size >= needed:
            return output_buf.value
        else:
            output_buf_size = needed

print get_short_path_name(u"C:\\Users\\zvi\\Desktop\\אאאאא")         

Any idea?

zvi
  • 3,677
  • 2
  • 30
  • 48
  • Change your code to use `_GetShortPathNameW = ctypes.WinDLL('kernel32', use_last_error=True).GetShortPathNameW`. Then if `needed == 0`, the call has failed, so raise an exception via `raise ctypes.WinError(ctypes.get_last_error())`. – Eryk Sun Apr 11 '19 at 15:25
  • For whatever reason you're using this, it is probably the wrong answer. It won't be portable to all installations of Windows. The system drive is NTFS, for which generating short filenames is *optional*. I always disable it because it's a waste of time and space to force every non-ASCII and/or long filename to paired with a legacy 8.3 DOS name. – Eryk Sun Apr 11 '19 at 15:30
  • Also, [ReFs](https://learn.microsoft.com/en-us/windows-server/storage/refs/refs-overview) doesn't even provide an option to support short names. – Eryk Sun Apr 11 '19 at 15:36

1 Answers1

1

This will likely convert incorrectly from a Python 2.x string to a Windows wide string due to Python 2.x not using abstract Unicode representation for str.

Instead, Python 2.x has a unicode datatype separate from str and plain string literals you specify are not unicode by default.

It would probably be best to use Python 3.x, but failing that, using an explicit unicode string might work:

print get_short_path_name(u"C:\\Users\\zvi\\Desktop\\אאאאא")

(note the u prefix in front of the string)

blubberdiblub
  • 4,085
  • 1
  • 28
  • 30
  • 1
    Also, generally in Python 2 you'll want to save the source file as UTF-8 and define the [source encoding](https://www.python.org/dev/peps/pep-0263), e.g. `# -*- coding: utf-8 -*-`. – Eryk Sun Apr 11 '19 at 15:22
  • @blubberdiblub Thanks, but your answer give the same error. I updated the code in answer. – zvi Apr 14 '19 at 08:30