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

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

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

1276717 次浏览

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

无论哪种方式,您都可以使用os.walk来执行此操作:

os.walk(directory)

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

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

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

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

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

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

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

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

如果您只需要当前目录的子目录,请将os.listdiros.path.isdir合并

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

谢谢你的提示,伙计们。我遇到了一个软链接(无限递归)作为目录返回的问题。软链接?我们不想要任何臭软链接!所以…

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

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

使用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)

使用全路径并占路径为...\\..\\..\\subfolder等:

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

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

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

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

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

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

基于Eli Bendersky的解决方案,使用以下示例:

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

使用过滤器函数os.path.isdir overos.listdir()类似这样的filter(os.path.isdir,[os.path.join(os.path.abspath('PATH'),p) for p in os.listdir('PATH/')])

你可以使用glob.glob

from glob import globglob("/path/to/directory/*/", recursive = True)

不要忘记*之后的尾随/

虽然这个问题很久以前就已经回答过了。我想推荐使用pathlib模块,因为这是在Windows和Unix操作系统上工作的强大方式。

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

from pathlib import Pathpaths = list(Path('myhomefolder', 'folder').glob('**/*.txt'))
# all sorts of operationsfile = paths[0]file.namefile.stemfile.parentfile.suffix

仅列出目录

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

仅列出当前目录中的文件

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

比上面的好得多,因为你不需要几个os.path.join(),你将直接获得完整的路径(如果你愿意),你可以在python3.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快得多。


对所有功能的分析

tl; dr:
-如果您想获取文件夹的所有立即子目录,请使用os.scandir
-如果您想获取所有子目录,甚至嵌套子目录,请使用os.walk或-稍微快一点-上面的fast_scandir函数。
-永远不要仅对顶级子目录使用os.walk,因为它可能比os.scandir慢数百(!)倍。

  • 如果您运行下面的代码,请确保运行一次,以便您的操作系统访问该文件夹,丢弃结果并运行测试,否则结果将被搞砸。
  • 您可能希望混淆函数调用,但我测试了它,这并不重要。
  • 所有示例都将给出文件夹的完整路径。作为(Windows)路径对象的path lib示例。
  • os.walk的第一个元素将是基本文件夹。因此您不会只获得子目录。您可以使用fu.pop(0)将其删除。
  • 所有结果都不会使用自然排序。这意味着结果将按以下方式排序:1,10,2。要获得自然排序(1,2,10),请查看https://stackoverflow.com/a/48030307/2441026


搜索结果

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

使用W7x64、Python 3.8.1进行测试。

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

import timeimport osfrom glob import globfrom 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()

这个答案似乎并不存在。

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

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

from pathlib import Path
p = Path('./')
# All subdirectories in the current directory, not recursive.[f for f in p.iterdir() if f.is_dir()]

递归列出所有子目录,路径全局化可以与#0模式一起使用。

# This will also include the current directory '.'list(p.glob('**'))

请注意,单个*作为全局模式将非递归地包括文件和目录。要仅获取目录,可以附加尾随/,但这仅在直接使用全局库时有效,而不是在通过Pathlib使用全局库时有效:

import glob
# These three lines return both files and directorieslist(p.glob('*'))list(p.glob('*/'))glob.glob('*')
# Whereas this returns only directoriesglob.glob('*/')

所以Path('./').glob('**')匹配与glob.glob('**/', recursive=True)相同的路径。

Pathlib也可以通过PyPi上的Pathlib2模块。在Python 2.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]

我最近遇到了一个类似的问题,我发现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 namesreturn 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 namesreturn dirlist

请记住,entry.path使用子目录的绝对路径。如果您只需要文件夹名称,您可以使用entry.name代替。有关entry对象的更多详细信息,请参阅操作系统

ipython中复制粘贴友好:

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

输出print(folders)

['folderA', 'folderB']

这将列出文件树下的所有子目录。

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 direxcept FileNotFoundError:print('Invalid directory')

pathlib在3.4版中是新的

此函数具有给定的父函数directory,递归迭代其所有directoriesprints它在其中找到的所有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 ;")

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

import os
def get_sub_directory_paths(start_directory, sub_directories):"""This method iterates through all subdirectory paths of a givendirectory to collect all directory paths.
:param start_directory: The starting directory path.:param sub_directories: A List that all subdirectory paths will bestored 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

我就是这么做的。

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

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

import os
path = os.getcwd()
pathObject = os.walk(path)

这个路径对象是一个对象,我们可以通过以下方式获得一个数组

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)

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

import osimport glob
def list_dirs(path):return [os.path.basename(x) for x in filter(os.path.isdir, glob.glob(os.path.join(path, '*')))]

那里有很多不错的答案,但如果你来这里寻找一种简单的方法来一次获取所有文件或文件夹的列表。你可以利用Linux和Mac上提供的操作系统找到,它比os.walk快得多

import osall_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()

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

最简单的方法:

from pathlib import Pathfrom 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]

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

import osimport 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 = '    ' * depthprint(f'{spacer}+ {path.name}')

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

这个下面的类将能够获得给定目录中的文件、文件夹和所有子文件夹的列表

import osimport json
class GetDirectoryList():def __init__(self, path):self.main_path = pathself.absolute_path = []self.relative_path = []

def get_files_and_folders(self, resp, path):all = os.listdir(path)resp["files"] = []for file_folder in all:if file_folder != "." and file_folder != "..":if os.path.isdir(path + "/" + file_folder):resp[file_folder] = {}self.get_files_and_folders(resp=resp[file_folder], path= path + "/" + file_folder)else:resp["files"].append(file_folder)self.absolute_path.append(path.replace(self.main_path + "/", "") + "/" + file_folder)self.relative_path.append(path + "/" + file_folder)return resp, self.relative_path, self.absolute_path
@propertydef get_all_files_folder(self):self.resp = {self.main_path: {}}all = self.get_files_and_folders(self.resp[self.main_path], self.main_path)return all
if __name__ == '__main__':mylib = GetDirectoryList(path="sample_folder")file_list = mylib.get_all_files_folderprint (json.dumps(file_list))

示例目录看起来像

sample_folder/lib_a/lib_c/lib_e/__init__.pya.txt__init__.pyb.txtc.txtlib_d/__init__.py__init__.pyd.txtlib_b/__init__.pye.txt__init__.py

获取结果

[{"files": ["__init__.py"],"lib_b": {"files": ["__init__.py","e.txt"]},"lib_a": {"files": ["__init__.py","d.txt"],"lib_c": {"files": ["__init__.py","c.txt","b.txt"],"lib_e": {"files": ["__init__.py","a.txt"]}},"lib_d": {"files": ["__init__.py"]}}},["sample_folder/lib_b/__init__.py","sample_folder/lib_b/e.txt","sample_folder/__init__.py","sample_folder/lib_a/lib_c/lib_e/__init__.py","sample_folder/lib_a/lib_c/lib_e/a.txt","sample_folder/lib_a/lib_c/__init__.py","sample_folder/lib_a/lib_c/c.txt","sample_folder/lib_a/lib_c/b.txt","sample_folder/lib_a/lib_d/__init__.py","sample_folder/lib_a/__init__.py","sample_folder/lib_a/d.txt"],["lib_b/__init__.py","lib_b/e.txt","sample_folder/__init__.py","lib_a/lib_c/lib_e/__init__.py","lib_a/lib_c/lib_e/a.txt","lib_a/lib_c/__init__.py","lib_a/lib_c/c.txt","lib_a/lib_c/b.txt","lib_a/lib_d/__init__.py","lib_a/__init__.py","lib_a/d.txt"]]

使用os walk

sub_folders = []for dir, sub_dirs, files in os.walk(test_folder):sub_folders.extend(sub_dirs)
import ospath = "test/"files = [x[0] + "/" + y for x in os.walk(path) if len(x[-1]) > 0 for y in x[-1]]

对于像我这样只需要目录中直接文件夹名称的人来说,这在Windows上有效。

import os
for f in os.scandir(mypath):print(f.name)

这是一个简单的递归解

import osdef fn(dir=r"C:\Users\aryan\Downloads\opendatakit"):  # 1.Get file names from directoryfile_list = os.listdir(dir)res = []# print(file_list)for file in file_list:if os.path.isfile(os.path.join(dir, file)):res.append(file)else:result = fn(os.path.join(dir, file))if result:res.extend(fn(os.path.join(dir, file)))return res

res = fn()print(res)print(len(res))