Мне нужно пройти через папки с длинными именами файлов в Windows.
Я попытался использовать os.listdir()
, но он сбой с длинными именами путей, что плохо.
Я попытался использовать os.walk()
, но он игнорирует пути, длина которых превышает ~ 256, что хуже.
Я пробовал обходное решение для магического слова, описанное здесь здесь, но оно работает только с подключенными дисками, а не с UNC pathnames.
Вот пример с короткими именами путей, которые показывают, что 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\\*.*'
Любая идея о том, как обращаться с длинными именами путей или с UNC-именами unicode?
Edit:
Следуя предложению ниже, я создал некоторые тестовые функции для сравнения Python 2.7 и 3.3, и я добавил тест glob.glob
и os.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