获取当前目录中所有子目录的列表
Posted
技术标签:
【中文标题】获取当前目录中所有子目录的列表【英文标题】:Getting a list of all subdirectories in the current directory 【发布时间】:2010-11-01 16:32:00 【问题描述】:有没有办法在 Python 中返回当前目录中所有子目录的列表?
我知道您可以对文件执行此操作,但我需要获取目录列表。
【问题讨论】:
docs.python.org/3.4/library/os.html?highlight=os#os.listdirdocs.python.org/3.4/library/os.path.html#os.path.isdir 如果您正在寻找 pathlib 解决方案,请执行[f for f in data_path.iterdir() if f.is_dir()]
信用:***.com/a/44228436/1601580。这为您提供了字符串文件夹名称。不知何故,它也排除了 .
和 ..
感谢上帝。 Glob 解决方案也很有价值:glob.glob("/path/to/directory/*/")
.
【参考方案1】:
使用操作系统行走
sub_folders = []
for dir, sub_dirs, files in os.walk(test_folder):
sub_folders.extend(sub_dirs)
【讨论】:
【参考方案2】:仅列出目录
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)
【讨论】:
在 Mac OS 上无法使用。我认为问题在于 os.listdir 仅返回目录的名称而不是完整路径,但 os.path.isdir 仅在完整路径是目录时才返回 True。 如果您稍微修改该行,这将在当前目录之外工作: subdirs = filter(os.path.isdir, [os.path.join(dir,x) for x in os.listdir(目录)]) 很好的工作,避免定义 lambda 函数而直接传递函数。【参考方案3】:下面的这个类将能够获取给定目录中的文件、文件夹和所有子文件夹的列表
import os
import json
class GetDirectoryList():
def __init__(self, path):
self.main_path = path
self.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
@property
def 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_folder
print (json.dumps(file_list))
而示例目录看起来像
sample_folder/
lib_a/
lib_c/
lib_e/
__init__.py
a.txt
__init__.py
b.txt
c.txt
lib_d/
__init__.py
__init__.py
d.txt
lib_b/
__init__.py
e.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"
]
]
【讨论】:
【参考方案4】:这应该可以工作,因为它还创建了一个目录树;
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
获取相对于当前工作目录的元素。
【讨论】:
【参考方案5】:最简单的方法:
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]
【讨论】:
【参考方案6】:那里有很多不错的答案,但是如果您来这里寻找一种简单的方法来一次获取所有文件或文件夹的列表。您可以利用在 linux 和 mac 上提供的 find 操作系统,它比 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()
或
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
【讨论】:
哇,你刚刚救了我的命! (形象地)我有几个文件夹,但有数百万个文件,上面描述的所有方法都需要很长时间才能执行,这要快得多。【参考方案7】:Python 3.4 在标准库中引入了the pathlib
module,它提供了一种面向对象的方法来处理文件系统路径:
from pathlib import Path
p = Path('./')
# All subdirectories in the current directory, not recursive.
[f for f in p.iterdir() if f.is_dir()]
要递归列出所有子目录,path globbing can be used with the **
pattern.
# This will also include the current directory '.'
list(p.glob('**'))
请注意,单个 *
作为 glob 模式将非递归地包含文件和目录。要仅获取目录,可以附加尾随 /
,但这仅在直接使用 glob 库时有效,在通过 pathlib 使用 glob 时无效:
import glob
# These three lines return both files and directories
list(p.glob('*'))
list(p.glob('*/'))
glob.glob('*')
# Whereas this returns only directories
glob.glob('*/')
所以Path('./').glob('**')
匹配与glob.glob('**/', recursive=True)
相同的路径。
Pathlib 也可通过the pathlib2 module on PyPi. 在 Python 2.7 上使用
【讨论】:
要遍历子目录列表,这里有一个漂亮、简洁的语法:for f in filter(Path.is_dir, p.iterdir()):
您确定您的 glob 解决方案需要两颗星吗? gloab(*/)
还不够吗?无论如何,绝妙的答案,特别是为了您干净地使用pathlib
。如果它也允许递归,那么评论会很好,尽管从不需要的问题的标题中,未来的读者应该阅读您链接的文档。
谢谢@CharlieParker!我用有关递归和使用斜杠的详细信息更新了我的答案(包括注意在将**
与 pathlib 的 glob 一起使用时不需要斜杠。关于使用单个星号,这将非递归地匹配文件和目录。跨度>
glob.glob('**/', recursive=True)
不包含隐藏目录,但 Path('./').glob('**')
包含【参考方案8】:
通过从这里加入多个解决方案,这就是我最终使用的:
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, '*')))]
【讨论】:
【参考方案9】:比上面好多了,因为你不需要几个 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
& @ 更快987654328@ 并将返回所有子文件夹以及这些(子)子文件夹中的所有文件的列表:https://***.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;博士:
- 如果您想获取文件夹的所有 immediate 子目录,请使用 os.scandir
。
- 如果您想获得 所有 子目录,甚至是 嵌套 子目录,请使用 os.walk
或 - 稍微快一点 - 上面的 fast_scandir
函数。
- 切勿仅将 os.walk
用于***子目录,因为它可能比 os.scandir
慢数百(!)倍。
os.walk
的第一个元素将是基本文件夹。所以你不会只得到子目录。您可以使用fu.pop(0)
将其删除。
所有结果都不会使用自然排序。这意味着结果将按如下方式排序:1、10、2。要获得自然排序(1、2、10),请查看https://***.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()
【讨论】:
如果您在问题的早期提到您正在替换您配置的不同功能,那就太好了。无论如何,令人印象深刻的是你花时间做这件事。好工作。我个人更喜欢使用单个库,所以我喜欢using
pathlib` 如下 `[f for f in p.iterdir() if f.is_dir()]``
我有 50 个子目录,每个子目录都有数千个子目录。我刚刚尝试运行fast_scandir
,它需要一个多小时。这是正常的吗?有什么办法可以加快速度吗?
非常清晰和聪明的答案。谢谢!【参考方案10】:
我们可以使用 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)
【讨论】:
【参考方案11】:我就是这样做的。
import os
for x in os.listdir(os.getcwd()):
if os.path.isdir(x):
print(x)
【讨论】:
它不起作用。我想在 x 中你必须提供完整的路径来使用 isdir() 进行检查 您可能在使用 os.getcwd(); 时遇到问题;本质上,您可以做的是您可以获得绝对路径并使用它。 dir = os.path.dirname(os.path.abspath(文件)) 使用 os,pat.join() 为我工作。因为它有助于获得子目录的完整路径。【参考方案12】:函数返回给定文件路径中所有子目录的列表。将搜索整个文件树。
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
【讨论】:
【参考方案13】:这个函数,具有给定的父 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 ;")
【讨论】:
【参考方案14】:这将列出文件树正下方的所有子目录。
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 版的新功能
【讨论】:
【参考方案15】:在ipython
中复制粘贴友好:
import os
d='.'
folders = list(filter(lambda x: os.path.isdir(os.path.join(d, x)), os.listdir(d)))
print(folders)
的输出:
['folderA', 'folderB']
【讨论】:
在这种情况下 X 是什么? @AbhishekParikhx
是os.listdir(d)
创建的列表中的项目,因为listdir
将返回他使用filter
命令和os.path.isdir
的文件和文件夹以过滤掉任何文件从列表中。【参考方案16】:
完整路径和占路径为.
、..
、\\
、..\\..\\subfolder
等:
import os, pprint
pprint.pprint([os.path.join(os.path.abspath(path), x[0]) \
for x in os.walk(os.path.abspath(path))])
【讨论】:
【参考方案17】:我最近有一个类似的问题,我发现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 上使用,您需要删除上下文管理器 - 请参阅 ***.com/questions/41401417/… 这是正确的。我可以发誓我在某处读到上下文管理器是在 3.5 中实现的,但似乎我错了。【参考方案18】:使用 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 for f in p.iterdir() if f.is_dir()]
【参考方案19】:
import os
d = '.'
[os.path.join(d, o) for o in os.listdir(d)
if os.path.isdir(os.path.join(d,o))]
【讨论】:
请注意,在这种方法中,如果不在 '.' 上执行,您需要注意 abspath 问题 请注意,如果您不使用 cwd ('.'),这将不起作用,除非您在o
上执行 os.path.join
以获取完整路径,否则 @987654324 @ 将始终返回 false
帖子似乎已更新,修复了上述两个问题。
为避免两次调用os.path.join
,您可以先加入,然后使用os.path.isdir
过滤列表:filter(os.path.isdir, [os.path.join(d, o) for o in os.listdir(d)])
将 pathlib 与 [f for f in data_path.iterdir() if f.is_dir()]
或 glob 一起使用更简单,更易于阅读:glob.glob("/path/to/directory/*/")
。【参考方案20】:
这里有几个基于@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]
【讨论】:
【参考方案21】:您是指直接子目录,还是树下的每个目录?
无论哪种方式,您都可以使用os.walk
来执行此操作:
os.walk(directory)
将为每个子目录生成一个元组。三元组中的第一个条目是目录名,所以
[x[0] for x in os.walk(directory)]
应该递归地给你所有的子目录。
请注意,元组中的第二个条目是第一个条目的子目录列表,因此您可以改用它,但它不太可能为您节省太多。
但是,您可以使用它来提供直接子目录:
next(os.walk('.'))[1]
或者查看已经发布的其他解决方案,使用os.listdir
和os.path.isdir
,包括“How to get all of the immediate subdirectories in Python”。
【讨论】:
这样一个干净漂亮的答案。谢谢你。我不熟悉 next() 并认为此链接对处于类似情况的任何人都有帮助:***.com/questions/1733004/python-next-function 对于任何关心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 在网络驱动器上尝试这个性能测试,我想你会发现在这种情况下性能相当显着。
@UKMonkey 我相信你是对的,这样的用例可能会有很大的不同。【参考方案22】:
您可以在 Python 2.7 中使用 os.listdir(path) 获取子目录(和文件)的列表
import os
os.listdir(path) # list of subdirectories and files
【讨论】:
这也包括文件。 这个名字很容易混淆,因为“dir”不是指构成列表的对象,而是指容器目录。请检查您的单行答案,对于初学者来说很容易选择它们。 请注意os.listdir
列出了包括文件在内的目录内容。【参考方案23】:
这个答案似乎不存在。
directories = [ x for x in os.listdir('.') if os.path.isdir(x) ]
【讨论】:
如果您搜索当前工作目录以外的任何内容,这将始终返回一个空列表,这在技术上是 OP 想要做的,但不是很可重用。 directories = [ x for x in os.listdir(localDir) if os.path.isdir(localDir+x)【参考方案24】:虽然这个问题很久以前就已经回答了。我想推荐使用 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
等等
【讨论】:
【参考方案25】:你可以使用glob.glob
from glob import glob
glob("/path/to/directory/*/")
不要忘记*
后面的/
。
【讨论】:
不错。简单的。只是,它会在名称中留下尾随的/
如果您不能假定/
是文件夹分隔符,请执行以下操作:glob(os.path.join(path_to_directory, "*", ""))
这对子目录不起作用!要使用 glob,这里有完整的答案:Use a Glob() to find files recursively in Python?
要使 glob 递归,您只需添加以下参数 recursive=True
【参考方案26】:
在os.listdir()
上使用过滤函数os.path.isdir
像这样filter(os.path.isdir,[os.path.join(os.path.abspath('PATH'),p) for p in os.listdir('PATH/')])
【讨论】:
【参考方案27】:以 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>
是您要遍历的目录的路径。
【讨论】:
【参考方案28】:我更喜欢使用过滤器 (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 for f in p.iterdir() if f.is_dir()]
【参考方案29】:
因为我在使用 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
【讨论】:
【参考方案30】:感谢您的提示,伙计们。我遇到了将软链接(无限递归)作为目录返回的问题。软链接?我们不希望没有臭软的链接!所以...
这只是渲染了目录,而不是软链接:
>>> import os
>>> inf = os.walk('.')
>>> [x[0] for x in inf]
['.', './iamadir']
【讨论】:
什么是[x[0] for x in inf]
在 python 中调用所以我可以查一下?
@shinzou 这是一个列表理解。超级好用。还要查找dict理解。以上是关于获取当前目录中所有子目录的列表的主要内容,如果未能解决你的问题,请参考以下文章