167

我希望能够仅列出某个文件夹中的目录。这意味着我不想列出文件名,也不需要额外的子文件夹。

让我们看看一个例子是否有帮助。在当前目录中,我们有:

>>> 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 来返回顶层是低效/太多的。

4

20 回答 20

243

os.walk

os.walknext项目功能一起使用:

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

对于Python <=2.5 ,请使用:

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

这是如何工作的

os.walk是一个生成器,调用next将获得 3 元组形式的第一个结果(目录路径、目录名、文件名)。因此,[1]索引仅返回dirnames来自该元组的。

于 2008-09-26T23:57:04.597 回答
161

使用 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']
于 2008-09-26T19:06:57.477 回答
68

使用 os.path.isdir 过滤列表以检测目录。

filter(os.path.isdir, os.listdir(os.getcwd()))
于 2008-09-26T19:10:36.157 回答
19
directories=[d for d in os.listdir(os.getcwd()) if os.path.isdir(d)]
于 2008-09-26T19:04:46.907 回答
14

请注意,与其做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)
    ]
于 2008-09-26T22:32:50.947 回答
13

这似乎也有效(至少在 linux 上):

import glob, os
glob.glob('*' + os.path.sep)
于 2016-07-06T04:54:49.890 回答
11

使用列表理解,

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

我认为这是最简单的方法

于 2019-04-10T05:29:57.140 回答
9

只是补充一点,使用 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() 的过滤速度非常快。

于 2013-01-17T11:57:25.733 回答
6

一个非常简单和优雅的方法是使用它:

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

在您想要文件夹名称的同一文件夹中运行此脚本。它只会为您提供确切的直接文件夹名称(也没有文件夹的完整路径)。

于 2014-10-13T11:26:42.517 回答
3

Python 3.4将该pathlib模块引入标准库,它提供了一种面向对象的方法来处理文件系统路径:

from pathlib import Path

p = Path('./')
[f for f in p.iterdir() if f.is_dir()]
于 2020-07-20T18:17:01.010 回答
2
[x for x in os.listdir(somedir) if os.path.isdir(os.path.join(somedir, x))]
于 2008-09-26T19:05:26.733 回答
2

作为一个新手,我还不能直接发表评论,但这里有一个小的更正,我想添加到ΤZΩΤZΙΟΥ答案的以下部分:

如果您更喜欢完整路径名,请使用此功能:

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

否则会出现语法错误。

于 2011-01-27T18:25:17.837 回答
2

你也可以使用os.scandir

with os.scandir(os.getcwd()) as mydir:
    dirs = [i.name for i in mydir if i.is_dir()]

如果你想要完整的路径,你可以使用i.path.

使用 scandir() 代替 listdir() 可以显着提高还需要文件类型或文件属性信息的代码的性能,因为如果操作系统在扫描目录时提供了这些信息,os.DirEntry 对象就会公开这些信息。

于 2021-02-12T10:48:57.343 回答
2

2021 年答案使用glob

import glob, os

p = "/some/path/"
for d in glob.glob(p + "*" + os.path.sep):
  print(d)
于 2021-09-05T23:07:39.983 回答
1

对于完整路径名列表,我更喜欢此版本而不是此处的其他解决方案

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))]
于 2013-03-20T10:53:08.207 回答
1
scanDir = "abc"
directories = [d for d in os.listdir(scanDir) if os.path.isdir(os.path.join(os.path.abspath(scanDir), d))]
于 2017-09-18T16:04:06.760 回答
1

FWIW,该os.walk方法比列表理解和过滤方法快近 10 倍:

In [30]: %timeit [d for d in os.listdir(os.getcwd()) if os.path.isdir(d)]
1.23 ms ± 97.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [31]: %timeit list(filter(os.path.isdir, os.listdir(os.getcwd())))
1.13 ms ± 13.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [32]: %timeit next(os.walk(os.getcwd()))[1]
132 µs ± 9.34 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
于 2020-09-03T02:24:42.173 回答
0

像这样?

>>>> [path for path in os.listdir(os.getcwd()) if os.path.isdir(path)]
于 2008-09-26T19:05:26.247 回答
0

没有目录时不会失败的更安全的选项。

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 []
于 2017-07-21T08:01:34.193 回答
-1
-- 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
于 2018-02-26T23:25:35.863 回答