在Python中,如何获取文件的正确路径?

Ned*_*der 22 python windows filenames

Windows使用不区分大小写的文件名,因此我可以使用以下任何一个打开相同的文件:

r"c:\windows\system32\desktop.ini"
r"C:\WINdows\System32\DESKTOP.ini"
r"C:\WiNdOwS\SyStEm32\DeSkToP.iNi"
Run Code Online (Sandbox Code Playgroud)

鉴于这些路径中的任何一条,我怎样才能找到真实的案例?我希望他们都能产生:

r"C:\Windows\System32\desktop.ini"
Run Code Online (Sandbox Code Playgroud)

os.path.normcase不这样做,它只是降低了一切.os.path.abspath返回一个绝对路径,但这些路径中的每一个都是绝对的,所以它不会改变它们中的任何一个. os.path.realpath仅用于解析Windows没有的符号链接,因此它与Windows上的abspath相同.

有一种直截了当的方法吗?

Pau*_*ore 13

奈德的GetLongPathName回答并不奏效(至少不适合我).你需要调用GetLongPathName返回值GetShortPathname.使用pywin32简洁(ctypes解决方案看起来类似于Ned):

>>> win32api.GetLongPathName(win32api.GetShortPathName('stopservices.vbs'))
'StopServices.vbs'
Run Code Online (Sandbox Code Playgroud)


xvo*_*rsx 8

Ethan回答正确的文件名,而不是路径上的子文件夹名称.这是我的猜测:

def get_actual_filename(name):
    dirs = name.split('\\')
    # disk letter
    test_name = [dirs[0].upper()]
    for d in dirs[1:]:
        test_name += ["%s[%s]" % (d[:-1], d[-1])]
    res = glob.glob('\\'.join(test_name))
    if not res:
        #File not found
        return None
    return res[0]
Run Code Online (Sandbox Code Playgroud)


Ned*_*der 7

这个python-win32线程有一个答案,不需要第三方包或走树:

import ctypes

def getLongPathName(path):
    buf = ctypes.create_unicode_buffer(260)
    GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW
    rv = GetLongPathName(path, buf, 260)
    if rv == 0 or rv > 260:
        return path
    else:
        return buf.value
Run Code Online (Sandbox Code Playgroud)

  • 这不起作用。GetLongPathName 只扩展短文件名,所以如果你给它“C:\Progra~1”你会得到“C:\Program Files”,但如果你给它“C:\PROGRAM FILES”,它已经是一个长路径名,所以它不会改变它。 (2认同)

Eth*_*man 7

这是一个简单的,仅限stdlib的解决方案:

import glob
def get_actual_filename(name):
    name = "%s[%s]" % (name[:-1], name[-1])
    return glob.glob(name)[0]
Run Code Online (Sandbox Code Playgroud)

  • 它只修复文件名,而不是以前的子目录。我添加了另一个答案,基于这个 http://stackoverflow.com/a/14742779/1355726 (2认同)
  • 这似乎不起作用。此外,如果文件名中包含字符(这些字符是glob令牌),它将失败。如果确实触发了目录扫描,那么从病理上讲它也可能会变慢。 (2认同)

kxr*_*kxr 6

这个方法统一,缩短并修复了几种方法:仅限标准库; 转换所有路径部分(驱动器号除外); 相对或绝对路径; 驱动信件与否; tolarant:

def casedpath(path):
    r = glob.glob(re.sub(r'([^:/\\])(?=[/\\]|$)', r'[\1]', path))
    return r and r[0] or path
Run Code Online (Sandbox Code Playgroud)

而且这个处理UNC路径:

def casedpath_unc(path):
    unc, p = os.path.splitunc(path)
    r = glob.glob(unc + re.sub(r'([^:/\\])(?=[/\\]|$)', r'[\1]', p))
    return r and r[0] or path
Run Code Online (Sandbox Code Playgroud)


The*_*l_T 6

在 Python 3 中,您可以使用pathlib's resolve()

>>> from pathlib import Path

>>> str(Path(r"C:\WiNdOwS\SyStEm32\DeSkToP.iNi").resolve())
r'C:\Windows\System32\desktop.ini'
Run Code Online (Sandbox Code Playgroud)

  • 注意:有时在这种情况下,您可能会得到完全不同的路径,因为它正在解析链接(例如,如果您有一个“subst”驱动器,则最终可能会将其解析为“subst”指向的位置)。 (2认同)