当前位置: 首页 > 面试题库 >

使用Python在Windows上无法找到长名称的文件

公良飞尘
2023-03-14
问题内容

我需要在Windows中浏览带有长文件名的文件夹。

我尝试使用os.listdir(),但是它使用长路径名崩溃,这很糟糕。

我尝试使用os.walk(),但是它忽略的路径名长于〜256,这更糟。

我尝试了此处描述的魔术字变通方法,但它仅适用于映射驱动器,不适用于UNC路径名。

这是一个具有短路径名的示例,该示例表明UNC路径名不适用于魔术词技巧。

>>> os.listdir('c:\\drivers')
['nusb3hub.cat', 'nusb3hub.inf', 'nusb3hub.sys', 'nusb3xhc.cat', 'nusb3xhc.inf', 'nusb3xhc.sys']
>>> os.listdir('\\\\Uni-hq-srv6\\router')
['2009-04-0210', '2010-11-0909', ... ]

>>> mw=u'\\\\?\\'
>>> os.listdir(mw+'c:\\drivers')
[u'nusb3hub.cat', u'nusb3hub.inf', u'nusb3hub.sys', u'nusb3xhc.cat', u'nusb3xhc.inf', u'nusb3xhc.sys']
>>> os.listdir(mw+'\\\\Uni-hq-srv6\\router')

Traceback (most recent call last):
  File "<pyshell#160>", line 1, in <module>
    os.listdir(mw+'\\\\Uni-hq-srv6\\router')
WindowsError: [Error 123] The filename, directory name, or volume label syntax is incorrect: u'\\\\?\\\\\\Uni-hq-srv6\\router\\*.*'

关于如何处理长路径名或Unicode UNC路径名的任何想法吗?

编辑:

按照以下注释的建议,我创建了一些测试函数以比较Python
2.7和3.3,并添加了glob.globos.listdir之后的测试os.chdir

os.chdir没有如预期的帮助(见本评论)。

glob.glob是在Python 3.3中唯一可以更好地工作的方法,但只能在以下一种情况下使用:使用魔术字和驱动器名称。

这是我使用的代码(适用于2.7和3.3)。我现在正在学习Python,希望这些测试有意义:

from __future__ import print_function
import os, glob

mw = u'\\\\?\\'

def walk(root):
    n = 0
    for root, dirs, files in os.walk(root):
        n += len(files)
    return n

def walk_mw(root):
    n = 0
    for root, dirs, files in os.walk(mw + root):
        n += len(files)
    return n

def listdir(root):
    try:
        folders = [f for f in os.listdir(root) if os.path.isdir(os.path.join(root, f))]
        files = [f for f in os.listdir(root) if os.path.isfile(os.path.join(root, f))]
        n = len(files)
        for f in folders:
            n += listdir(os.path.join(root, f))
        return n
    except:
        return 'Crash'

def listdir_mw(root):
    if not root.startswith(mw):
        root = mw + root
    try:
        folders = [f for f in os.listdir(root) if os.path.isdir(os.path.join(root, f))]
        files = [f for f in os.listdir(root) if os.path.isfile(os.path.join(root, f))]
        n = len(files)
        for f in folders:
            n += listdir_mw(os.path.join(root, f))
        return n
    except:
        return 'Crash'

def listdir_cd(root):
    try:
        os.chdir(root)
        folders = [f for f in os.listdir('.') if os.path.isdir(os.path.join(f))]
        files = [f for f in os.listdir('.') if os.path.isfile(os.path.join(f))]
        n = len(files)
        for f in folders:
            n += listdir_cd(f)
        return n
    except:
        return 'Crash'

def listdir_mw_cd(root):
    if not root.startswith(mw):
        root = mw + root
    try:
        os.chdir(root)
        folders = [f for f in os.listdir('.') if os.path.isdir(os.path.join(f))]
        files = [f for f in os.listdir('.') if os.path.isfile(os.path.join(f))]
        n = len(files)
        for f in folders:
            n += listdir_cd(f) # the magic word can only be added the first time
        return n
    except:
        return 'Crash'

def glb(root):
    folders = [f for f in glob.glob(root + '\\*') if os.path.isdir(os.path.join(root, f))]
    files = [f for f in glob.glob(root + '\\*') if os.path.isfile(os.path.join(root, f))]
    n = len(files)
    for f in folders:
        n += glb(os.path.join(root, f))
    return n

def glb_mw(root):
    if not root.startswith(mw):
        root = mw + root
    folders = [f for f in glob.glob(root + '\\*') if os.path.isdir(os.path.join(root, f))]
    files = [f for f in glob.glob(root + '\\*') if os.path.isfile(os.path.join(root, f))]
    n = len(files)
    for f in folders:
        n += glb_mw(os.path.join(root, f))
    return n

def test():
    for txt1, root in [('drive ', r'C:\test'),
                    ('UNC   ', r'\\Uni-hq-srv6\router\test')]:
        for txt2, func in [('walk                    ', walk),
                           ('walk     magic word     ', walk_mw),
                           ('listdir                 ', listdir),
                           ('listdir  magic word     ', listdir_mw),
                           ('listdir              cd ', listdir_cd),
                           ('listdir  magic word  cd ', listdir_mw_cd),
                           ('glob                    ', glb),
                           ('glob     magic word     ', glb_mw)]:
            print(txt1, txt2, func(root))

test()

结果如下:

  • 数字8表示找到了所有文件
  • 数字0表示它甚至没有尝试就不会崩溃
  • 1到7之间的任何数字表示失败了一半而没有崩溃
  • 这个词Crash意味着它崩溃了

--

Python 2.7
drive  walk                     5
drive  walk     magic word      8      * GOOD *
drive  listdir                  Crash
drive  listdir  magic word      8      * GOOD *
drive  listdir              cd  Crash
drive  listdir  magic word  cd  5
drive  glob                     5
drive  glob     magic word      0
UNC    walk                     6
UNC    walk     magic word      0
UNC    listdir                  5
UNC    listdir  magic word      Crash
UNC    listdir              cd  5
UNC    listdir  magic word  cd  Crash
UNC    glob                     5
UNC    glob     magic word      0

Python 3.3
drive  walk                     5
drive  walk     magic word      8      * GOOD *
drive  listdir                  Crash
drive  listdir  magic word      8      * GOOD *
drive  listdir              cd  Crash
drive  listdir  magic word  cd  5
drive  glob                     5
drive  glob     magic word      8      * GOOD *
UNC    walk                     6
UNC    walk     magic word      0
UNC    listdir                  5
UNC    listdir  magic word      Crash
UNC    listdir              cd  5
UNC    listdir  magic word  cd  Crash
UNC    glob                     5
UNC    glob     magic word      0

问题答案:

使用8.3后备以避免长路径名,在Win7资源管理器中浏览,这似乎是Windows本身所做的,即每个长路径都有一个较短的“真实名称”:

>>> long_unc="\\\\K53\\Users\\Tolan\\testing\\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\xxxxxxxxxxxxxxxxxxxxxxxxdddddddddddddddddddddwgggggggggggggggggggggggggggggggggggxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\esssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggeee"
>>> os.listdir(long_unc)
FileNotFoundError: [WinError 3]

但是您可以使用win32api(pywin32)“构建”较短的版本,即

short_unc=win32api.GetShortPathName(win32api.GetShortPathName(win32api.GetShortPathName("\\\\K53\\Users\\Tolan\\testing\\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")+"\\xxxxxxxxxxxxxxxxxxxxxxxxdddddddddddddddddddddwgggggggggggggggggggggggggggggggggggxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") + "\\esssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggeee")
>>> print(short_unc)
\\K53\Users\Tolan\testing\XXXXXX~1\XXXXXX~1\ESSSSS~1
>>> import os
>>> os.listdir(short_unc)
['test.txt']

显然,您可以将win32api.GetShortPathName调用折叠到目录浏览中,而不是像我的示例中那样嵌套。我已经通过3次调用做到了这一点,因为如果您已经拥有“太长”的路径,则win32api.GetShortPathName也无法解决它,但是您可以按目录进行操作并保持在限制以下。



 类似资料:
  • 我在我的项目中使用 jQuery 时遇到了问题(使用 Angular 和 boosted,这是引导程序的一个分支)。错误如下: 文件夹/包含/my/component.ts中的错误:错误TS2581:找不到名称“$”。您需要为jQuery安装类型定义吗?尝试。 我已经安装了< code>@types/jquery和< code>jquery,并且在angular.json文件中添加了脚本:

  • 问题内容: 我尝试运行时遇到问题: 我得到: 我遵循以下过程:使用Pip安装Python软件包时如何使用MinGW的gcc编译器?。 我安装了MinGW,并检查了C ++编译器选项 我将MinGW添加到了自己的路径 这是我的路 我用以下几行创建了distutils.cfg compiler=mingw32 在这里: 仍然出现相同的错误,不确定我在做什么错。 我正在使用Windows 8系统(32位

  • 问题内容: 我在Linux机器上有一个项目,其中包含带有在Windows中被认为是非法/保留的字符的文件(http://msdn.microsoft.com/zh- cn/library/aa365247%28VS.85%29.aspx )。该项目在多个文件夹中有10,000多个文件,我将确定这些文件的路径。 我可以为每个非法/保留字符,但是有一种更简单的方法来查找包含以下内容的所有文件 确定后,

  • 问题内容: 我正在为我的Python模块编写文档(使用Sphinx和reST),并且发现当交叉引用其他Python对象(模块,类,函数等)时,完整的对象名最终变得非常长。通常它的长度超过80个字符,我不惜一切代价避免。 这是一个例子: 问题是,在为 ReallyLongExampleClassName 类创建文档时,我为完整路径名生成了它。 我想知道是否有办法解决这个问题?我尝试了以下方法,但没有

  • 我正在使用一些windows脚本,这些脚本涉及使用sqlplus后台处理文件。我不断收到错误: 我能够将问题限制在一个相当小的范围内:在windows中,我无法假脱机一些名称以点开头的文件。在windows cmd中,我输入了sqlplus 然后尝试了以下命令: 很奇怪,只有<代码>。测试失败。但这正是我所需要的。我在Linux中尝试了相同的命令,没有问题。我在windows上使用sqlplus

  • 我正在Intellij IDEA中启动一个新项目,当我选择JDK时,所有显示的都是JDK16.0.1,我需要JDK8(已经安装),所以我单击“Add JDK...”我浏览了我的文件,我只能找到JDK16。注意:我的桌面上有JDK 8