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

947

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

我知道可以获取文件列表,但我需要获取目录列表。


4
https://docs.python.org/3.4/library/os.html?highlight=os#os.listdirhttps://docs.python.org/3.4/library/os.path.html#os.path.isdir - The Demz
23
如果您正在寻找pathlib解决方案,请使用[f for f in data_path.iterdir() if f.is_dir()]。这将返回文件夹名称作为字符串,还会自动排除...,非常感谢。另外,glob.glob解决方案也很有价值:glob.glob("/path/to/directory/*/") - Charlie Parker
35个回答

1
很多回复!在审查所有建议后,我筛选出了三个候选人来列出树中的所有文件夹以及两种列出直接文件夹的方法。
每个文件夹:
dirs_rglob = [x for x in folder.rglob('*') if x.is_dir()]
dirs_walk = [x[0] for x in os.walk(folder)]
dirs_custom = fast_scandir(folder)

其中fast_scandir()是由用户136036建议的自定义函数,请参见下面的代码。我使用以下Python代码测试了性能:

from pathlib import Path
from os import walk,scandir
from time import monotonic

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

folder = Path('c:/xampp/htdocs/fonts') # Insert your path here 
msg = 'Using {}, seconds: {}, number of folders: {}.\n'

start = monotonic()
dirs_rglob = [x for x in folder.rglob('*') if x.is_dir()]
print(msg.format('Path.rglob', monotonic() - start, len(dirs_rglob)))

start = monotonic()
dirs_walk = [x[0] for x in walk(folder)]
print(msg.format('os.walk', monotonic() - start, len(dirs_walk)))

start = monotonic()
dirs_custom = fast_scandir(folder)
print(msg.format('fast_scandir', monotonic() - start, len(dirs_custom)))

正如用户136036所述,他的自定义方法是最快的,但与os.walk(folder)相比并不多,而folder.rglob('*')真的非常慢。由于自定义方法并没有快多少,我使用os.walk(folder),因为后者对于系统文件夹或回收站在Windows操作系统中没有问题。

如果您只需要立即文件夹的列表,可以使用

dirs_iter = [ f for f in folder.iterdir()  if f.is_dir()]
dirs_scan = [ f.path for f in os.scandir(folder)  if f.is_dir()]

经过测试,两种方法的运行时间都非常短,其中folder.iterdir()方法有时略微更快。

总之:对于整个子目录树,请使用os.walk(folder),对于直接子目录,请使用folder.iterdir()os.scandir(folder)


0
下面这个类可以获取给定目录中所有文件、文件夹和子文件夹的列表。
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"
  ]
]

这段代码会抛出一个错误:AttributeError: 'dict' object has no attribute 'append'~\AppData\Local\Temp\ipykernel_12328\702766901.py in () 32 #mylib = GetDirectoryList(path="sample_folder") 33 mylib = GetDirectoryList(os.getcwd()) ---> 34 file_list = mylib.get_all_files_folder 35 print (json.dumps(file_list))``` - Rich Lysakowski PhD

0

这是一个简单的递归解决方案

import os
def fn(dir=r"C:\Users\aryan\Downloads\opendatakit"):  # 1.Get file names from directory
    file_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))

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

0

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

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 获取相对于当前工作目录的元素。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接