获取当前目录下所有子目录的列表

947

有没有办法在Python中返回当前目录中所有子目录的列表?

我知道可以获取文件列表,但我需要获取目录列表。


4
https://docs.python.org/3.4/library/os.html?highlight=os#os.listdirhttps://docs.python.org/3.4/library/os.path.html#os.path.isdir - The Demz
23
如果您正在寻找pathlib解决方案,请使用[f for f in data_path.iterdir() if f.is_dir()]。这将返回文件夹名称作为字符串,还会自动排除...,非常感谢。另外,glob.glob解决方案也很有价值:glob.glob("/path/to/directory/*/") - Charlie Parker
35个回答

14
虽然这个问题很久以前就已经有了答案,我想建议使用pathlib模块,因为这是在Windows和Unix操作系统上工作的一种强大的方式。

所以要获取特定目录中包括子目录的所有路径:

from pathlib import Path
paths = list(Path('myhomefolder', 'folder').glob('**/*.txt'))

# all sorts of operations
file = paths[0]
file.name
file.stem
file.parent
file.suffix

等等。


14

既然我在使用Python 3.4和Windows UNC路径时遇到了这个问题,那么这里提供一个适用于这种环境的变体:

from pathlib import WindowsPath

def SubDirPath (d):
    return [f for f in d.iterdir() if f.is_dir()]

subdirs = SubDirPath(WindowsPath(r'\\file01.acme.local\home$'))
print(subdirs)

Pathlib在Python 3.4中新增,可以更轻松地处理不同操作系统下的路径:

https://docs.python.org/3.4/library/pathlib.html

12

ipython中可复制粘贴:

import os
d='.'
folders = list(filter(lambda x: os.path.isdir(os.path.join(d, x)), os.listdir(d)))

print(folders)的输出结果:

['folderA', 'folderB']

2
在这种情况下,X是什么? - Abhishek Parikh
1
@AbhishekParikh x 是由 os.listdir(d) 创建的列表中的项,因为 listdir 将返回文件和文件夹,他正在使用 filter 命令与 os.path.isdir 过滤掉列表中的任何文件。 - James Burke

11

谢谢大家的建议。我遇到了一个问题,即软链接(无限递归)被返回为目录。软链接?我们不需要那些臭软链接!因此……

这只呈现了目录,而不是软链接:

>>> import os
>>> inf = os.walk('.')
>>> [x[0] for x in inf]
['.', './iamadir']

2
在Python中,[x[0] for x in inf]被称为什么,这样我就可以查找它了? - shinzou
3
那是一个列表推导式。非常有用。还可以查找字典推导式。 - KurtB

10

这里有一些基于 @Blair Conrad 示例的简单函数 -

import os

def get_subdirs(dir):
    "Get a list of immediate subdirectories"
    return next(os.walk(dir))[1]

def get_subfiles(dir):
    "Get a list of immediate subfiles"
    return next(os.walk(dir))[2]

未能正常工作。报告“StopIteration”。 - KansaiRobot

10

这就是我所做的方式。

    import os
    for x in os.listdir(os.getcwd()):
        if os.path.isdir(x):
            print(x)

它不起作用。我猜在 x 中,您必须提供完整的路径以使用 isdir() 进行检查。 - niranjan patidar
你可能在使用os.getcwd()时遇到了问题;实际上,你可以获取绝对路径并使用它代替。dir = os.path.dirname(os.path.abspath(file)) - Mujeeb Ishaque
使用os和pat.join()对我很有帮助,因为它可以获取子目录的完整路径。 - niranjan patidar

9
在Eli Bendersky的解决方案基础上,使用以下示例:
import os
test_directory = <your_directory>
for child in os.listdir(test_directory):
    test_path = os.path.join(test_directory, child)
    if os.path.isdir(test_path):
        print test_path
        # Do stuff to the directory "test_path"

其中<your_directory>是您希望遍历的目录路径。


7

完整路径需要考虑以下情况:...\\..\\..\\subfolder 等内容。

import os, pprint
pprint.pprint([os.path.join(os.path.abspath(path), x[0]) \
    for x in os.walk(os.path.abspath(path))])

7

最简单的方法:

from pathlib import Path
from glob import glob

current_dir = Path.cwd()
all_sub_dir_paths = glob(str(current_dir) + '/*/') # returns list of sub directory paths

all_sub_dir_names = [Path(sub_dir).name for sub_dir in all_sub_dir_paths] 

我不会说那是最简单的,而且混合使用旧式的“glob”模块和新式的“pathlib”模块是不必要的复杂操作(需要在“str”和“Path”对象之间进行不断的转换)。如果你想演示“pathlib”模块,尽可能地使用“pathlib”模块;它更漂亮,更清晰易懂(与你的代码依赖于末尾的“/”来使“glob.glob”不返回文件相比,“Path.glob”没有复制这种行为):“all_sub_dir_names = [pth.name for pth in Path.cwd().iterdir() if pth.is_dir()]”。 - ShadowRanger

5

我最近也遇到了类似的问题,我发现对于Python 3.6来说(正如用户Havlock所述),最好的答案是使用os.scandir。因为似乎没有使用它的解决方案,那么我就提供一下我的解决方案。首先是一个非递归的解决方案,只列出根目录下直接子目录。

def get_dirlist(rootdir):

    dirlist = []

    with os.scandir(rootdir) as rit:
        for entry in rit:
            if not entry.name.startswith('.') and entry.is_dir():
                dirlist.append(entry.path)

    dirlist.sort() # Optional, in case you want sorted directory names
    return dirlist

递归版本如下所示:
def get_dirlist(rootdir):

    dirlist = []

    with os.scandir(rootdir) as rit:
        for entry in rit:
            if not entry.name.startswith('.') and entry.is_dir():
                dirlist.append(entry.path)
                dirlist += get_dirlist(entry.path)

    dirlist.sort() # Optional, in case you want sorted directory names
    return dirlist

请记住,entry.path代表子目录的绝对路径。如果你只需要文件夹名称,可以使用entry.name。有关entry对象的详细信息,请参阅os.DirEntry


实际上,这样写的话在3.5版本上是行不通的,只能在3.6版本上使用。如果要在3.5版本上使用,需要删除上下文管理器 - 参见https://dev59.com/YlgR5IYBdhLWcg3wXcam - havlock
这是正确的。我能发誓我在某个地方读到上下文管理器是在3.5中实现的,但看来我错了。 - Alberto A

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接