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

我知道您可以对文件执行此操作,但我需要获得目录列表。


当前回答

我就是这么做的。

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

其他回答

这应该可以工作,因为它还创建了一个目录树;

import os
import pathlib

def tree(directory):
    print(f'+ {directory}')
    print("There are " + str(len(os.listdir(os.getcwd()))) + \
    " folders in this directory;")
    for path in sorted(directory.glob('*')):
        depth = len(path.relative_to(directory).parts)
        spacer = '    ' * depth
        print(f'{spacer}+ {path.name}')

这应该列出使用pathlib库的文件夹中的所有目录。path.relative_to(目录)。Parts获取相对于当前工作目录的元素。

import os
path = "test/"
files = [x[0] + "/" + y for x in os.walk(path) if len(x[-1]) > 0 for y in x[-1]]

比上面的要好得多,因为你不需要几个os.path.join(),你将直接获得完整的路径(如果你愿意的话),你可以在Python 3.5及以上版本中这样做。

subfolders = [ f.path for f in os.scandir(folder) if f.is_dir() ]

这将给出子目录的完整路径。 如果您只想要子目录的名称,请使用f.name而不是f.path

https://docs.python.org/3/library/os.html#os.scandir


稍微OT:如果你需要递归所有子文件夹和/或递归所有文件,看看这个函数,它比os更快。Walk & glob将返回所有子文件夹以及这些(子)子文件夹中的所有文件的列表:https://stackoverflow.com/a/59803793/2441026

如果你只需要递归的所有子文件夹:

def fast_scandir(dirname):
    subfolders= [f.path for f in os.scandir(dirname) if f.is_dir()]
    for dirname in list(subfolders):
        subfolders.extend(fast_scandir(dirname))
    return subfolders

返回所有子文件夹及其完整路径的列表。这个还是比os快。走,比glob快多了。


所有功能的分析

tl;博士: -如果你想获取一个文件夹的所有直接子目录,请使用os.scandir。 —如果您想获取所有子目录,甚至是嵌套的子目录,请使用os。行走或者——稍微快一点——上面的fast_scandir函数。 —不要使用操作系统。只遍历顶级子目录,因为它可能比os.scandir慢数百倍(!)。

If you run the code below, make sure to run it once so that your OS will have accessed the folder, discard the results and run the test, otherwise results will be screwed. You might want to mix up the function calls, but I tested it, and it did not really matter. All examples will give the full path to the folder. The pathlib example as a (Windows)Path object. The first element of os.walk will be the base folder. So you will not get only subdirectories. You can use fu.pop(0) to remove it. None of the results will use natural sorting. This means results will be sorted like this: 1, 10, 2. To get natural sorting (1, 2, 10), please have a look at https://stackoverflow.com/a/48030307/2441026

结果:

os.scandir      took   1 ms. Found dirs: 439
os.walk         took 463 ms. Found dirs: 441 -> it found the nested one + base folder.
glob.glob       took  20 ms. Found dirs: 439
pathlib.iterdir took  18 ms. Found dirs: 439
os.listdir      took  18 ms. Found dirs: 439

用W7x64测试,Python 3.8.1。

# -*- coding: utf-8 -*-
# Python 3


import time
import os
from glob import glob
from pathlib import Path


directory = r"<insert_folder>"
RUNS = 1


def run_os_walk():
    a = time.time_ns()
    for i in range(RUNS):
        fu = [x[0] for x in os.walk(directory)]
    print(f"os.walk\t\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")


def run_glob():
    a = time.time_ns()
    for i in range(RUNS):
        fu = glob(directory + "/*/")
    print(f"glob.glob\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")


def run_pathlib_iterdir():
    a = time.time_ns()
    for i in range(RUNS):
        dirname = Path(directory)
        fu = [f for f in dirname.iterdir() if f.is_dir()]
    print(f"pathlib.iterdir\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")


def run_os_listdir():
    a = time.time_ns()
    for i in range(RUNS):
        dirname = Path(directory)
        fu = [os.path.join(directory, o) for o in os.listdir(directory) if os.path.isdir(os.path.join(directory, o))]
    print(f"os.listdir\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")


def run_os_scandir():
    a = time.time_ns()
    for i in range(RUNS):
        fu = [f.path for f in os.scandir(directory) if f.is_dir()]
    print(f"os.scandir\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms.\tFound dirs: {len(fu)}")


if __name__ == '__main__':
    run_os_scandir()
    run_os_walk()
    run_glob()
    run_pathlib_iterdir()
    run_os_listdir()

谢谢你们的建议,伙计们。我遇到了软链接(无限递归)作为dirs返回的问题。Softlinks吗?我们不想要臭软链接!所以…

这只是渲染dirs,而不是软链接:

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

d = '.'
[os.path.join(d, o) for o in os.listdir(d) 
                    if os.path.isdir(os.path.join(d,o))]