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


Answers:


602

您是指直接子目录,还是树下的每个目录?

无论哪种方式,您都可以使用os.walk以下方法:

os.walk(directory)

将为每个子目录生成一个元组。该三元组中的第一个条目是目录名称,因此

[x[0] for x in os.walk(directory)]

应该递归地给你所有的子目录。

请注意,该元组中的第二个条目是该条目的子目录列表的第一个位置,因此您可以改用它,但是不太可能为您节省很多。

但是,您可以使用它来为您提供直接的子目录:

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

或者使用os.listdir和查看已经发布的其他解决方案os.path.isdir,包括“ 如何在Python中获取所有直接子目录 ”中的解决方案。


7
我认为os.walk返回三元组(根,目录,文件)。这意味着dirs有很多重复的条目。有没有更有效的方法可以通过目录进行递归?
mathtick 2010年

22
请勿直接使用os.walk('.').next()[1]或使用os.walk('.').__next__()[1]。相反,请使用内置函数next(),该函数在Python 2(请参阅doc)Python 3(请参阅doc)中都可用。例如:next(os.walk('.'))[1]
Lucio Paiva

1
@Lucio为什么os.walk('.').next()[1]直接使用不好?
wisbucky

8
@wisbucky这是一个不好的做法,因为它iteraror.__next__()是一种内部方法,iterator.next()next()根据PEP-3114 将用法转换为内置方法。参见2007
Lucio Paiva 2015年

16
对于关注性能差异的人os.walkos.listdir+ os.path.isdir解决方案:我只是测试的10,000子目录(以百万计的在下面的层次结构中的文件)的目录和性能上的差异可以忽略不计。os.walk:“ 10个循环,每个循环最好3:44.6毫秒”和os.listdir+ os.path.isdir:“ 10个循环,每个循环最好3:45.1毫秒”
kevinmicke 17-02-28

166
import os

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

5
请注意,如果未在'。'上执行,则在这种方法中您需要注意abspath问题。
daspostloch,2011年

4
抬起头来,如果您不使用cwd('。'),除非您继续执行以获取完整路径,否则它将无法正常工作,否则将始终返回falseos.path.joinoisdir(0)
James McMahon

5
似乎该帖子已针对上述两个问题进行了修复。
cgmb

1
为避免os.path.join再次拨打电话,您可以先加入,然后使用os.path.isdir以下方法过滤列表: filter(os.path.isdir, [os.path.join(d, o) for o in os.listdir(d)])
–quant_dev

154

你可以用 glob.glob

from glob import glob
glob("/path/to/directory/*/")

别忘了/之后的尾随*


真好 简单。只是,它留下了/名字的尾随
juanmirocks

9
如果您不能假定/是文件夹分隔符,请执行以下操作:glob(os.path.join(path_to_directory, "*", ""))
juanmirocks

1
这对子目录不起作用!要使用glob,这里是完整的答案:使用Glob()在Python中递归查找文件?
poppie

1
要使glob递归,您可以添加以下参数recursive=True
JacoSolari

102

比上面的要好得多,因为您不需要几个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.walk和快得多glob


所有功能分析

tl; dr:
-如果要获取文件夹使用的所有直接子目录os.scandir
-如果要获取所有子目录,甚至嵌套的子目录,请使用os.walk或-稍微快一点- fast_scandir上面的函数。
-从来不使用os.walk只顶级子目录,因为它可以是数百倍慢于(!) os.scandir

  • 如果您运行下面的代码,请确保运行一次,以便您的操作系统可以访问该文件夹,丢弃结果并运行测试,否则结果将被弄乱。
  • 您可能想混淆函数调用,但是我对其进行了测试,但这并不重要。
  • 所有示例都将提供文件夹的完整路径。pathlib示例作为(Windows)Path对象。
  • 的第一个元素os.walk将是基本文件夹。因此,您将不会仅获得子目录。您可以使用fu.pop(0)将其删除。
  • 所有结果都不会使用自然排序。这意味着将对结果进行如下排序:1、10、2。要进行自然排序(1、2、10),请查看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()

35

如果您需要一个可在子目录中找到所有子目录的递归解决方案,请按照之前的建议使用walk。

如果仅需要当前目录的子目录,请os.listdiros.path.isdir




19

您可以使用os.listdir(path)获取Python 2.7中的子目录(和文件)列表

import os
os.listdir(path)  # list of subdirectories and files

59
这也包括文件。
TarnayKálmán2014年

2
名称令人困惑,因为“ dir”并不指向构成列表的对象,而是指向容器目录。请检查您的单行答案,对于初学者来说,选择它们非常诱人。
Titou

4
当心os.listdir列出目录的内容,包括文件。
guneysus

13

仅列出目录

print("\nWe are listing out only the directories in current directory -")
directories_in_curdir = filter(os.path.isdir, os.listdir(os.curdir))
print(directories_in_curdir)

仅列出当前目录中的文件

files = filter(os.path.isfile, os.listdir(os.curdir))
print("\nThe following are the list of all files in the current directory -")
print(files)

2
在Mac OS上不起作用。我认为问题在于os.listdir仅返回目录名称,而不返回完整路径,但是os.path.isdir仅在完整路径为目录时返回True。
denson

如果您稍稍修改以下行,则可在当前目录之外运行:subdirs = filter(os.listdir(dir)中的x的os.path.isdir,[os.path.join(dir,x)])
RLC

12

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

from pathlib import Path

p = Path('./')

# List comprehension
[f for f in p.iterdir() if f.is_dir()]

# The trailing slash to glob indicated directories
# This will also include the current directory '.'
list(p.glob('**/'))

也可以通过PyPi上的pathlib2模块在 Python 2.7 上使用Pathlib。


要遍历子目录列表,可以使用一种简洁的语法:for f in filter(Path.is_dir, p.iterdir()):
Bryan Roach

11

由于我使用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


10

尽管很久以前就回答了这个问题。我想建议使用该pathlib模块,因为这是在Windows和Unix OS上工作的可靠方法。

因此,要获取特定目录(包括子目录)中的所有路径:

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

等等


9

谢谢提醒伙计。我遇到了一个以dirs返回的软链接(无限递归)的问题。软链接?我们不希望没有臭味的软链接!所以...

这仅显示目录,而不显示软链接:

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

1
什么[x[0] for x in inf]叫python,所以我可以查一下吗?
shinzou

2
@shinzou这是一个列表理解。超级有用。还要查找字典理解。
KurtB

9

复制粘贴友好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用于从列表中过滤掉任何文件的文件和文件夹。
詹姆斯·伯克

8

这就是我的方法。

    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

7

这是基于@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]

6

在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>您要遍历的目录的路径在哪里。


5

有了完整路径和占路感...\\..\\..\\subfolder,等:

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

4

这个答案似乎还不存在。

directories = [ x for x in os.listdir('.') if os.path.isdir(x) ]

7
如果您正在搜索除当前工作目录以外的任何内容,这将始终返回一个空列表,从技术上讲,这是OP想要执行的操作,但不太可重用。
ochawkeye '17

2
目录= [x代表os.listdir(localDir)中的x,如果os.path.isdir(localDir + x)
Poonam

3

我最近有一个类似的问题,我发现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改用。有关该对象的更多详细信息,请参考os.DirEntryentry


实际上,编写此代码的方式在3.5(仅3.6)上不起作用。要在3.5上使用,您需要删除上下文管理器-请参阅stackoverflow.com/questions/41401417/…–
havlock

这是对的。我可以发誓我在某处读到上下文管理器是在3.5中实现的,但是看来我错了。
艾伯托

1

os.path.isdiros.listdir() 这样的东西使用过滤器功能filter(os.path.isdir,[os.path.join(os.path.abspath('PATH'),p) for p in os.listdir('PATH/')])


1

这将在文件树的右边列出所有子目录。

import pathlib


def list_dir(dir):
    path = pathlib.Path(dir)
    dir = []
    try:
        for item in path.iterdir():
            if item.is_dir():
                dir.append(item)
                dir = dir + list_dir(item)
        return dir
    except FileNotFoundError:
        print('Invalid directory')

pathlib 是3.4版的新功能


1

返回给定文件路径中所有子目录的列表的函数。将搜索整个文件树。

import os

def get_sub_directory_paths(start_directory, sub_directories):
    """
    This method iterates through all subdirectory paths of a given 
    directory to collect all directory paths.

    :param start_directory: The starting directory path.
    :param sub_directories: A List that all subdirectory paths will be 
        stored to.
    :return: A List of all sub-directory paths.
    """

    for item in os.listdir(start_directory):
        full_path = os.path.join(start_directory, item)

        if os.path.isdir(full_path):
            sub_directories.append(full_path)

            # Recursive call to search through all subdirectories.
            get_sub_directory_paths(full_path, sub_directories)

return sub_directories

1

我们可以使用os.walk()获取所有文件夹的列表

import os

path = os.getcwd()

pathObject = os.walk(path)

这个pathObject是一个对象,我们可以通过

arr = [x for x in pathObject]

arr is of type [('current directory', [array of folder in current directory], [files in current directory]),('subdirectory', [array of folder in subdirectory], [files in subdirectory]) ....]

我们可以通过遍历arr并打印中间数组来获取所有子目录的列表

for i in arr:
   for j in i[1]:
      print(j)

这将打印所有子目录。

要获取所有文件:

for i in arr:
   for j in i[2]:
      print(i[0] + "/" + j)

0

具有给定父级的该函数以递归方式directory遍历其所有函数directories以及printsfilenames其中找到的所有函数。太有用了。

import os

def printDirectoryFiles(directory):
   for filename in os.listdir(directory):  
        full_path=os.path.join(directory, filename)
        if not os.path.isdir(full_path): 
            print( full_path + "\n")


def checkFolders(directory):

    dir_list = next(os.walk(directory))[1]

    #print(dir_list)

    for dir in dir_list:           
        print(dir)
        checkFolders(directory +"/"+ dir) 

    printDirectoryFiles(directory)       

main_dir="C:/Users/S0082448/Desktop/carpeta1"

checkFolders(main_dir)


input("Press enter to exit ;")

0

通过从此处加入多个解决方案,这就是我最终使用的方法:

import os
import glob

def list_dirs(path):
    return [os.path.basename(x) for x in filter(
        os.path.isdir, glob.glob(os.path.join(path, '*')))]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.