Как перечислить только каталоги верхнего уровня в Python? - PullRequest
105 голосов
/ 26 сентября 2008

Я хочу иметь возможность перечислять только каталоги внутри какой-либо папки. Это означает, что я не хочу, чтобы имена файлов были в списке, и при этом я не хочу дополнительные подпапки.

Посмотрим, поможет ли пример. В текущем каталоге мы имеем:

>>> 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 только для возвращения верхнего уровня неэффективно / слишком много.

Ответы [ 16 ]

157 голосов
/ 27 сентября 2008

os.walk

Использование os.walk с next Функция элемента:

next(os.walk('.'))[1]

Для Python <= 2,5 </em> используйте:

os.walk('.').next()[1]

Как это работает

os.walk является генератором, и вызов next получит первый результат в виде 3-х кортежей (dirpath, dirnames, filenames). Таким образом, индекс [1] возвращает только dirnames из этого кортежа.

96 голосов
/ 26 сентября 2008

Отфильтруйте результат, используя 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']
42 голосов
/ 26 сентября 2008

Отфильтруйте список, используя os.path.isdir для обнаружения каталогов.

filter(os.path.isdir, os.listdir(os.getcwd()))
12 голосов
/ 26 сентября 2008
directories=[d for d in os.listdir(os.getcwd()) if os.path.isdir(d)]
10 голосов
/ 27 сентября 2008

Обратите внимание, что вместо 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)
    ]
8 голосов
/ 17 января 2013

Просто добавьте, что использование 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 () очень немного быстрее.

6 голосов
/ 13 октября 2014

Очень простой и элегантный способ использовать это:

 import os
 dir_list = os.walk('.').next()[1]
 print dir_list

Запустите этот сценарий в той же папке, для которой вы хотите указать имена папок. Он даст вам только непосредственное имя папки (тоже без полного пути к папкам).

5 голосов
/ 06 июля 2016

Кажется, это тоже работает (по крайней мере, в Linux):

import glob, os
glob.glob('*' + os.path.sep)
2 голосов
/ 10 апреля 2019

Использование списка понимания,

[a for a in os.listdir() if os.path.isdir(a)]

Я думаю, что это самый простой способ

2 голосов
/ 27 января 2011

будучи новичком здесь, я пока не могу напрямую комментировать, но вот небольшая поправка, которую я хотел бы добавить к следующей части ΤΖΩΤΖΙΟΥ ответа :

Если вы предпочитаете полные пути, используйте эту функцию:

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 </strong>: внутренняя конструкция должна быть списком, а не кортежем, и поэтому должна читаться так:

def listdirs(folder):  
  return [
    d for d in [os.path.join(folder, d1) for d1 in os.listdir(folder)]
    if os.path.isdir(d)
  ]

в противном случае возникает синтаксическая ошибка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...