首页 > 解决方案 > 如何在Python中递归解决目录路径问题?

问题描述

我正在执行 REST API 调用来获取 SharePoint 文档库的文件夹。

我想递归地获取整个目录树中的所有文件夹路径。

我编写了一个函数来从给定文件夹中获取子文件夹列表,但不确定如何遍历到第 N 个目录并获取所有文件夹路径。

例如,假设当前的 SharePoint 文档库结构为以下 JSON(fo=文件夹;f=文件):

{
  "root": [
    {
      "fo1": {
        "fo1": "f1",
        "fo2": ["f1", "f2"]
      },
      "fo2": ["fi1", "fi2"]
    },
    "fi1","fi2"]
}

从上面的例子中,我想要一个所有文件夹/目录的路径列表:例如输出应该是:

["/root/fo1/", "/root/fo1/fo1/", "/root/fo1/fo2/", "/root/fo2/"]

因为它是一个 REST API 调用,所以我事先不知道结构,直到我运行获取子文件夹的查询,然后进入每个子文件夹以获取它们各自的子文件夹。

我编写的当前(以下)函数正在获取数据直到 1 级(子文件夹,因为它是基于内部迭代而不是递归),我如何实现基于递归的解决方案以获取所有唯一文件夹路径作为列表?

def print_root_contents(ctx):

    try:
        list_object = ctx.web.lists.get_by_title('Documents')
        folder = list_object.root_folder
        ctx.load(folder)
        ctx.execute_query()

        folders = folder.folders
        ctx.load(folders)
        ctx.execute_query()

        for myfolder in folders:
            print("For Folder : {0}".format(myfolder.properties["Name"]))
            folder_list, files_list = print_folder_contents(ctx, myfolder.properties["Name"])
            print("Sub folders - ", folder_list)
            print("Files - ", files_list)

    except Exception as e:
        print('Problem printing out library contents: ', e)


def print_folder_contents(ctx, folder_name):

    try:
        folder = ctx.web.get_folder_by_server_relative_url("/sites/abc/Shared Documents/"+folder_name+"/")
        ctx.load(folder)
        ctx.execute_query()

        # Folders
        fold_names = []
        sub_folders = folder.folders
        ctx.load(sub_folders)
        ctx.execute_query()
        for s_folder in sub_folders:
            # folder_name = folder_name+"/"+s_folder.properties["Name"]
            # print("Folder name: {0}".format(folder.properties["Name"]))
            fold_names.append(s_folder.properties["Name"])

        return fold_names

    except Exception as e:
        print('Problem printing out library contents: ', e)

在上面的最后一个函数 (print_folder_contents) 中,我无法形成一个递归逻辑来保持递归地追加文件夹和子文件夹,并在第 n 个文件夹中没有更多文件夹时停止它并继续下一个同级文件夹上一级。

发现它真的很有挑战性。有什么帮助吗?

标签: pythonif-statementrecursioniterationpython-3.6

解决方案


您可以使用生成器函数迭代 dict 项并生成 dict 键和 yield 键,并与递归调用生成的路径连接,如果给定一个列表,则递归生成从列表项上的递归调用生成的内容:

def paths(d):
    def _paths(d):
        if isinstance(d, dict):
            for k, v in d.items():
                yield k + '/'
                for p in _paths(v):
                    yield '/'.join((k, p))
        elif isinstance(d, list):
            for i in d:
                yield from _paths(i)
    return ['/' + p for p in _paths(d)]

所以给出:

d = {
  "root": [
    {
      "fo1": {
        "fo1": "f1",
        "fo2": ["f1", "f2"]
      },
      "fo2": ["fi1", "fi2"]
    },
    "fi1","fi2"]
}

paths(d)返回:

['/root/', '/root/fo1/', '/root/fo1/fo1/', '/root/fo1/fo2/', '/root/fo2/']

请注意,您的预期输出应该包括'/root/',因为根文件夹也应该是一个有效的文件夹。


推荐阅读