Как перечислить только каталоги верхнего уровня в Python?

StackOverflow https://stackoverflow.com/questions/141291

  •  02-07-2019
  •  | 
  •  

Вопрос

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

Давайте посмотрим, поможет ли вам пример.В текущем каталоге у нас есть:

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

Это было полезно?

Решение

Отфильтруйте результат с помощью 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']

Другие советы

ос.ходить

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

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

Для Питон <=2.5 использование:

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

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

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

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

filter(os.path.isdir, os.listdir(os.getcwd()))
directories=[d for d in os.listdir(os.getcwd()) if os.path.isdir(d)]

Обратите внимание, что вместо того, чтобы делать 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)
    ]

Просто добавлю, что использование 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

Фильтрация операционной системы.listdir() выполняется ненамного быстрее.

Гораздо более простым и элегантным способом является использование этого:

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

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

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

import glob, os
glob.glob('*' + os.path.sep)

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

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

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

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

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

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

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

[x for x in os.listdir(somedir) if os.path.isdir(os.path.join(somedir, x))]

Для получения списка полных путей я предпочитаю эту версию другой Решения здесь:

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))]
scanDir = "abc"
directories = [d for d in os.listdir(scanDir) if os.path.isdir(os.path.join(os.path.abspath(scanDir), d))]

Более безопасный вариант, который не дает сбоя при отсутствии каталога.

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 []

Вот так?

>>>> [path for path in os.listdir(os.getcwd()) if os.path.isdir(path)]
-- 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top