Как перечислить только каталоги верхнего уровня в Python?
Я хочу иметь возможность перечислять только каталоги внутри некоторой папки.
Это означает, что я не хочу перечислять имена файлов, а также не хочу добавлять дополнительные подпапки.
Посмотрим, поможет ли пример. В текущем каталоге мы имеем:
>>> os.listdir(os.getcwd())
['cx_Oracle-doc', 'DLLs', 'Doc', 'include', 'Lib', 'libs', 'LICENSE.txt', 'mod_p
ython-wininst.log', 'NEWS.txt', 'pymssql-wininst.log', 'python.exe', 'pythonw.ex
e', 'README.txt', 'Removemod_python.exe', 'Removepymssql.exe', 'Scripts', 'tcl',
'Tools', 'w9xpopen.exe']
Однако я не хочу, чтобы имена файлов были перечислены. Мне также не нужны подпапки, такие как \Lib\curses. По сути, я хочу работать со следующим:
>>> for root, dirnames, filenames in os.walk('.'):
... print dirnames
... break
...
['cx_Oracle-doc', 'DLLs', 'Doc', 'include', 'Lib', 'libs', 'Scripts', 'tcl', 'Tools']
Однако мне интересно, есть ли более простой способ достижения тех же результатов. У меня создается впечатление, что использование os.walk только для возврата верхнего уровня неэффективно/слишком много.
Ответы
Ответ 1
Отфильтруйте результат с помощью os.path.isdir() (и используйте os.path.join(), чтобы получить реальный путь):
>>> [ name for name in os.listdir(thedir) if os.path.isdir(os.path.join(thedir, name)) ]
['ctypes', 'distutils', 'encodings', 'lib-tk', 'config', 'idlelib', 'xml', 'bsddb', 'hotshot', 'logging', 'doc', 'test', 'compiler', 'curses', 'site-packages', 'email', 'sqlite3', 'lib-dynload', 'wsgiref', 'plat-linux2', 'plat-mac']
Ответ 2
os.walk
Используйте os.walk
со next
функцией item:
next(os.walk('.'))[1]
Для Python <= 2.5 используйте:
os.walk('.').next()[1]
Как это работает
os.walk
- это генератор, и вызов next
приведет к получению первого результата в виде 3-х кортежей (dirpath, dirnames, filenames). Таким образом, индекс [1]
возвращает только dirnames
из этого кортежа.
Ответ 3
Отфильтруйте список, используя os.path.isdir для обнаружения каталогов.
filter(os.path.isdir, os.listdir(os.getcwd()))
Ответ 4
directories=[d for d in os.listdir(os.getcwd()) if os.path.isdir(d)]
Ответ 5
Обратите внимание, что вместо выполнения os.listdir(os.getcwd())
предпочтительнее сделать os.listdir(os.path.curdir)
. Еще один вызов функции, и он переносится.
Итак, чтобы завершить ответ, чтобы получить список каталогов в папке:
def listdirs(folder):
return [d for d in os.listdir(folder) if os.path.isdir(os.path.join(folder, d))]
Если вы предпочитаете полные пути, используйте эту функцию:
def listdirs(folder):
return [
d for d in (os.path.join(folder, d1) for d1 in os.listdir(folder))
if os.path.isdir(d)
]
Ответ 6
Просто добавьте, что использование os.listdir() не требует много обработки и очень просто os.walk(). next() [1] ". Это связано с тем, что os.walk() использует os.listdir() внутри. Фактически, если вы проверите их вместе:
>>>> import timeit
>>>> timeit.timeit("os.walk('.').next()[1]", "import os", number=10000)
1.1215229034423828
>>>> timeit.timeit("[ name for name in os.listdir('.') if os.path.isdir(os.path.join('.', name)) ]", "import os", number=10000)
1.0592019557952881
Фильтрация os.listdir() выполняется очень немного быстрее.
Ответ 7
Очень простой и элегантный способ заключается в том, чтобы использовать это:
import os
dir_list = os.walk('.').next()[1]
print dir_list
Запустите этот script в той же папке, для которой вы хотите, чтобы имена папок. Это даст вам точно имя сразу только для папок (это тоже без полного пути к папкам).
Ответ 8
Это тоже работает (по крайней мере, на Linux):
import glob, os
glob.glob('*' + os.path.sep)
Ответ 9
будучи новичком здесь, я еще не могу прямо комментировать, но вот небольшая коррекция, которую я хотел бы добавить к следующей части ответа ΤΖΩΤΖΙΟΥ:
Если вы предпочитаете полные пути, используйте эту функцию:
def listdirs(folder):
return [
d for d in (os.path.join(folder, d1) for d1 in os.listdir(folder))
if os.path.isdir(d)
]
для тех, кто все еще находится на python < 2.4: внутренняя конструкция должна быть списком вместо кортежа и поэтому должна выглядеть следующим образом:
def listdirs(folder):
return [
d for d in [os.path.join(folder, d1) for d1 in os.listdir(folder)]
if os.path.isdir(d)
]
в противном случае возникает синтаксическая ошибка.
Ответ 10
[x for x in os.listdir(somedir) if os.path.isdir(os.path.join(somedir, x))]
Ответ 11
Для списка имен полного пути я предпочитаю эту версию для других решений здесь:
def listdirs(dir):
return [os.path.join(os.path.join(dir, x)) for x in os.listdir(dir)
if os.path.isdir(os.path.join(dir, x))]
Ответ 12
scanDir = "abc"
directories = [d for d in os.listdir(scanDir) if os.path.isdir(os.path.join(os.path.abspath(scanDir), d))]
Ответ 13
Вот так?
>>>> [path for path in os.listdir(os.getcwd()) if os.path.isdir(path)]
Ответ 14
Более безопасная опция, которая не сбой, когда нет каталога.
def listdirs(folder):
if os.path.exists(folder):
return [d for d in os.listdir(folder) if os.path.isdir(os.path.join(folder, d))]
else:
return []
Ответ 15
Используя понимание списка,
[a for a in os.listdir() if os.path.isdir(a)]
Я думаю, что это самый простой способ
Ответ 16
-- This will exclude files and traverse through 1 level of sub folders in the root
def list_files(dir):
List = []
filterstr = ' '
for root, dirs, files in os.walk(dir, topdown = True):
#r.append(root)
if (root == dir):
pass
elif filterstr in root:
#filterstr = ' '
pass
else:
filterstr = root
#print(root)
for name in files:
print(root)
print(dirs)
List.append(os.path.join(root,name))
#print(os.path.join(root,name),"\n")
print(List,"\n")
return List