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

评论

docs.python.org/3.4/library/os.html?highlight=os#os.listdir docs.python.org/3.4/library/os.path.html#os.path.isdir

如果您正在寻找pathlib解决方案,请执行[如果f.is_dir()中的f用于data_path.iterdir()中的f]功劳:stackoverflow.com/a/44228436/1601580。这将为您提供字符串文件夹名称。不知何故它也排除在外。和..感谢上帝。 Glob解决方案也值得:glob.glob(“ / path / to / directory / * /”)。

#1 楼

您是指直接子目录,还是树下的每个目录?
无论哪种方式,您都可以使用os.walk来做到这一点:

os.walk(directory)


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

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


应递归地提供所有子目录。

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

但是,您可以使用它只是为了给您直接的子目录:

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


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

评论


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

–mathtick
2010年8月18日在21:59

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

– Lucio Paiva
2015年1月1日在21:49



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

– Wisbucky
2015年9月2日,2:30

@wisbucky这是一个不好的做法,因为iteraror .__ next __()是内部方法,应根据PEP-3114将iterator.next()的用法转换为内置的next()。参见2007年批准的PEP-3114。

– Lucio Paiva
2015年9月2日在2:57



对于任何关心os.walk和os.listdir + os.path.isdir解决方案之间的性能差异的人:我只是在具有10,000个子目录(在下面的层次结构中具有数百万个文件)的目录上进行了测试,性能差异可以忽略不计。 os.walk:“ 10个循环,每个循环最好3:44.6毫秒”和os.listdir + os.path.isdir:“ 10个循环,每个循环最好3:45.1毫秒”

–kevinmicke
17年2月28日在19:05

#2 楼

您可以只使用glob.glob

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


不要忘了/之后的尾随*

评论


真好简单。仅,它在名称中保留尾随/

– juanmirocks
18年3月21日在16:00

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

– juanmirocks
18-3-21在16:17



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

– poppie
18-10-12在8:22



要使glob递归,您只需添加以下参数recursive = True

–JacoSolari
19年11月12日在12:39

#3 楼

import os

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


评论


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

– daspostloch
2011年5月29日23:26
请注意,如果您不使用cwd('。'),则除非您对o执行os.path.join以获取完整路径,否则它将无法正常工作,否则isdir(0)始终返回false

–詹姆斯·麦克马洪
2012年8月22日20:32



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

–cgmb
2015年11月12日在9:14

为了避免两次调用os.path.join,可以先加入,然后使用os.path.isdir过滤列表:filter(os.path.isdir,[os.path.join(d,o)for os in。 listdir(d)])

–quant_dev
19 Jun 14'15:11



将pathlib与[如果f.is_dir()中的f用于data_path.iterdir()中的f一起使用]或glob则更简单易读:glob.glob(“ / path / to / directory / * /”)。

–查理·帕克(Charlie Parker)
7月20日16:32

#4 楼

比上面的要好得多,因为您不需要几个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.walkglob更快,并且将返回所有子文件夹以及这些(子)子文件夹中的所有文件的列表: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快得多。


所有函数的分析

-如果需要要获取文件夹的所有直接子目录,请使用os.scandir
-如果要获取所有子目录(甚至嵌套的子目录),请使用os.walk或-稍微快一点-上面的fast_scandir函数。顶层子目录,因为它可能比os.walk慢数百倍(!)。


如果运行下面的代码,请确保运行一次,以确保操作系统具有进入文件夹,丢弃结果并运行测试,否则结果将被弄乱。
您可能想混用函数调用,但是我对其进行了测试,但这并不重要。
所有示例都将提供文件夹的完整路径。 pathlib示例作为(Windows)Path对象。
os.scandir的第一个元素将是基本文件夹。因此,您将不会仅获得子目录。您可以使用os.walk删除它。

所有结果都不会使用自然排序。这意味着将对结果进行如下排序: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()


评论


如果您在问题的早期提到要替换要配置的不同功能,那将是很好的。无论如何,您花费的时间都令人印象深刻。做得好。我个人更喜欢使用一个库,所以我喜欢使用pathlib`,如下所示

–查理·帕克(Charlie Parker)
7月20日下午16:29

我有50个子目录,每个子目录都有数千个子目录。我刚刚尝试运行fast_scandir,这花了一个多小时。这正常吗?我有什么办法可以加快速度?

– Vincent
8月18日5:12

#5 楼

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

评论


使用pathlib更简单:[如果f.is_dir(),则f在p.iterdir()中为f]

–查理·帕克(Charlie Parker)
7月20日下午16:26

@CharlieParker:这个答案比pathlib早了几年。

– Eli Bendersky
7月20日下午16:53

#6 楼

我更喜欢使用过滤器(https://docs.python.org/2/library/functions.html#filter),但这只是一个问题。

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


评论


使用pathlib更简单:[如果f.is_dir(),则f在p.iterdir()中为f]

–查理·帕克(Charlie Parker)
7月20日16:26



#7 楼

使用python-os-walk实现了这一点。 (http://www.pythonforbeginners.com/code-snippets-source-code/python-os-walk/)

import os

print("root prints out directories only from what you specified")
print("dirs prints out sub-directories from root")
print("files prints out all files from root and directories")
print("*" * 20)

for root, dirs, files in os.walk("/var/log"):
    print(root)
    print(dirs)
    print(files)


评论


使用pathlib更简单:[如果f.is_dir(),则f在p.iterdir()中为f]

–查理·帕克(Charlie Parker)
7月20日下午16:29

#8 楼

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

p = Path('./')

# All subdirectories in the current directory, not recursive.
[f for f in p.iterdir() if f.is_dir()]


请注意,单个**作为glob模式将非递归地包含文件和目录。要仅获取目录,可以附加尾随的*,但这仅在直接使用glob库时才有效,而不是在通过pathlib使用glob时起作用:也可以通过PyPi上的pathlib2模块在Python 2.7上使用Pathlib。

评论


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

–布莱恩·罗奇(Bryan Roach)
19-10-26 8:00



您确定您的球形解决方案需要两颗星吗? gloab(* /)还不够吗?无论如何,都是神话般的答案,特别适合您干净使用pathlib。如果它也允许递归,那么最好评论一下,尽管不需要问题的标题,以后的读者应该阅读您链接的文档。

–查理·帕克(Charlie Parker)
7月20日下午16:26

谢谢@CharlieParker!我用有关递归和尾随斜杠的详细信息更新了我的答案(包括注意,将**与pathlib的glob一起使用时,不需要尾随斜杠。关于单个星号,这将以非递归方式匹配文件和目录。

– joelostblom
7月20日18:14

#9 楼

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

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


评论


这也包括文件。

–塔纳伊·卡尔曼(TarnayKálmán)
14-10-14在23:20

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

–头投
16-09-16在11:05



注意os.listdir列出目录的内容,包括文件。

– Guneysus
16-10-26在6:56

#10 楼

仅列出目录

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)


评论


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

– Denson
16-11-22在17:52

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

–RLC
19年5月7日在17:15



避免定义lambda函数,而直接传递函数,可以很好地完成工作。

–查理·帕克(Charlie Parker)
7月20日下午16:29

#11 楼

由于我在使用Python 3.4和Windows UNC路径时偶然发现了此问题,因此这是此环境的一种变体:

不同的操作系统更容易:
https://docs.python.org/3.4/library/pathlib.html

#12 楼

虽然很久以前就回答了这个问题。我想建议使用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


等。

#13 楼

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

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

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


评论


在python中调用[inf中的x的[x [0]]是什么,以便我可以查找?

– Shinzou
17年12月23日在13:45

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

– KurtB
18-2-23在14:39

#14 楼

ipython中友好复制粘贴:

评论


在这种情况下X是多少?

– Abhishek Parikh
18-10-28在5:11

@AbhishekParikh x是os.listdir(d)创建的列表中的项,因为listdir将返回他正在使用带有os.path.isdir的filter命令从列表中过滤出任何文件的文件和文件夹。

–詹姆斯·伯克(James Burke)
19年5月28日在18:35



#15 楼

这就是我的方法。

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


评论


它不起作用。我想在x中,您必须提供完整的路径来使用isdir()检查

– niranjan patidar
3月20日9:21

您可能在使用os.getcwd()时遇到了麻烦;本质上,您可以做的是获取绝对路径并使用它。 dir = os.path.dirname(os.path.abspath(file))

– Mujeeb Ishaque
3月20日12:33



使用os,pat.join()对我有用。因为它有助于获取子目录的完整路径。

– niranjan patidar
3月25日17:32

#16 楼

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


#17 楼

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

#18 楼

使用完整路径并考虑路径为...\..\..\subfolder等,

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


#19 楼

这个答案似乎还不存在。

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


评论


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

–ochawkeye
17-2-23在19:13



目录= [x对于os.listdir(localDir)中的x,如果os.path.isdir(localDir + x)

–Poonam
18年2月15日在6:53

#20 楼

最近我有一个类似的问题,我发现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上使用,您需要删除上下文管理器-请参见stackoverflow.com/questions/41401417/…

– havlock
18年4月1日在9:39

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

– Alberto A
18年4月2日在19:58

#21 楼

最简单的方法:
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] 


#22 楼

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

#23 楼

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

#24 楼

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

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


#25 楼

我们可以使用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)


#26 楼

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

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, '*')))]


#27 楼

具有给定父级directory的此函数以递归方式遍历其所有directories,并以prints遍历其在其中找到的所有filenames。太有用了。

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 ;")



#28 楼

那里有很多不错的答案,但是如果您是来这里寻找简单的方法一次获取所有文件或文件夹的列表。您可以利用linux和mac上提供的os,它比os.walk要快得多。
import os
all_files_list = os.popen("find path/to/my_base_folder -type f").read().splitlines()
all_sub_directories_list = os.popen("find path/to/my_base_folder -type d").read().splitlines()

OR
import os

def get_files(path):
    all_files_list = os.popen(f"find {path} -type f").read().splitlines()
    return all_files_list

def get_sub_folders(path):
    all_sub_directories_list = os.popen(f"find {path} -type d").read().splitlines()
    return all_sub_directories_list


#29 楼

这应该起作用,因为它还会创建目录树;
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(directory).parts获取相对于当前工作目录的元素。