【问题标题】:How to get Windows short file name in python?如何在 python 中获取 Windows 短文件名?
【发布时间】:2014-06-29 04:21:22
【问题描述】:

我需要从我的 python 代码中确定 Windows 短文件名。为此,我可以使用 win32api 找到解决方案。

import win32api
long_file_name='C:\Program Files\I am a file'
short_file_name=win32api.GetShortPathName(long_file_name)

参考:http://blog.lowkster.com/2008/10/spaces-in-directory-names-i-really-love.html

不幸的是,我需要安装 pywin32ActivePython,这在我的情况下是不可能的。

也参考了 SO:

在 python 中获取短路径:Getting short path in python

【问题讨论】:

  • 请注意,在 NTFS 中生成短文件名是可选的,建议在目录包含数千个文件的系统上禁用,因为它会显着降低访问速度,并且 ReFS 和 exFAT 根本不支持短文件名.有多种更好的方法可以绕过经典的 DOS MAX_PATH 限制 - 例如“\\?\”设备路径、子/映射驱动器、安装点(连接点)和符号链接。

标签: python python-2.7 python-3.x


【解决方案1】:

您可以使用ctypes。根据the documentation on MSDNGetShortPathNameKERNEL32.DLL。请注意,真正的函数是 GetShortPathNameW 用于 wide (Unicode) 字符,GetShortPathNameA 用于单字节字符。由于宽字符更通用,我们将使用该版本。首先,根据文档设置原型:

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

GetShortPathName 在没有目标缓冲区的情况下首先调用它来使用。它将返回创建目标缓冲区所需的字符数。然后,您使用该大小的缓冲区再次调用它。如果由于TOCTTOU 问题,返回值仍然较大,请继续尝试直到正确为止。所以:

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

【讨论】:

  • 嗨,这段代码对我来说似乎很完美,除非我添加了最后一个文件夹。你知道为什么吗?这是路径C:\data\SIEA\_0 Mise à niveau des boites\Zone NRA de Ferney\Ornex 04-05\APD_e\06_Fichier Adresse - IPE
  • 调用可能失败。所以使用kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) 而不是ctypes.windll.kernel32。然后如果needed == 0,通过raise ctypes.WinError(ctypes.get_last_error()) 引发异常。
  • 非常方便!我要提出的唯一建议是从output_buf_size=len(long_name) 开始,因为short_path 很少比输入路径长。
  • @ErykSun 评论的简短附录:作为一种简单的速记,您可以使用if needed == 0: raise ctypes.WinError(),这将为您执行GetLastError()。我也不需要这样指定use_last_error=True,而是YMMV。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-26
  • 2013-04-18
相关资源
最近更新 更多