No se pueden localizar archivos con nombres largos en Windows con Python

Necesito recorrer las carpetas con nombres de archivo largos en Windows.

Traté de usaros.listdir(), pero se bloquea con largas rutas de acceso, lo cual es malo.

Traté de usaros.walk(), pero ignora las rutas de acceso más largas que ~ 256, lo que es peor.

Probé la solución mágica palabra descritaaquí, pero solo funciona con unidades asignadas, no conNombres de ruta UNC.

Aquí hay un ejemplo con rutas cortas, que muestra que las rutas UNC no funcionan con el truco de la palabra mágica.

>>> 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\\*.*'

¿Alguna idea de cómo tratar con las rutas de acceso largas o con las rutas de acceso UNC de Unicode?

Editar:

Siguiendo la sugerencia de los comentarios a continuación, creé algunas funciones de prueba para comparar Python 2.7 y 3.3, y agregué la prueba deglob.glob yos.listdir despuésos.chdir.

losos.chdir no ayudó como se esperaba (ver estocomentario).

losglob.glob es el único que en Python 3.3 funciona mejor, pero solo en una condición: usar la palabra mágica y con el nombre de la unidad.

Aquí está el código que utilicé (funciona tanto en 2.7 como en 3.3). Estoy aprendiendo Python ahora, y espero que estas pruebas tengan sentido:

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()

Y aqui esta el resultado:

El número 8 significa que se encontraron todos los archivos.El número 0 significa que ni siquiera intentó sin chocar.Cualquier número entre 1 y 7 significa que falló a mitad de camino sin estrellarseLa palabraCrash significa que se estrelló

-

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

Respuestas a la pregunta(3)

Su respuesta a la pregunta