如何动态迭代子目录

时间:2018-04-27 21:11:08

标签: python iteration

我在多种情况下遇到过这个问题。

这里有一个用例,比如我有一个目录结构,可以包含未知的子目录层,我想得到rootdir下的文件总数。动态迭代这棵树的最佳方法是什么?

这是文件夹结构的一个示例:

rootdir
   -> subdir1
     ->file1
          -> subsubdir1
                 -> file1
                 -> file2
          -> subsubdir2
                 -> file1
          -> subsubdir3
                 -> file1
                 -> subsubsubdir
                    -> file1
   -> subdir2
          -> subsubdirA
                 -> file1
                 -> file2
          -> subsubdirB
                 -> file1
                 -> file2

我从API调用获取文件夹结构,而不是直接从文件系统获取。这是api响应的一部分。假设这是我从调用rootdir获得的,然后我想保存子文件夹id [1,2],然后进入每个子文件夹并迭代查找子文件夹是否存在的相同过程同时保持计数文件。

响应包括total_count,即项目数(一个子文件夹将计为1)。因此,我需要跟踪子文件夹ID,并为每个子文件夹启动一个新的api调用,以获取每个子文件夹(以及可能的子文件夹)中的文件数,同时跟踪总数文件。 (希望我能清楚地解释一下。如果有什么不清楚,请随意发表评论。)

{

"item_collection":{"total_count":3,
    "entries":[
    {"type":"folder","id":"1","sequence_id":"0","etag":"0"},
    {"type":"folder","id":"2","sequence_id":"0","etag":"0"},
    {"type":"file","id":"3","file_version"{"type":"file_version","id":"303835527128"},"sequence_id":"0","etag":"0",}
    ],
]}
}

这是我到目前为止所做的,但我不确定如何跟踪每个子文件夹并动态迭代它们。任何帮助表示赞赏!

def total_file_count(client, folder_id):
    total_file_count = 0
    subfolder_ids = []
    folder = client.get_folder(folder_id=folder_id)
    item_count = folder['item_collection']['total_count']
    subfolder = True

    if item_count > 0:
        while subfolder:
            for i in folder['item_collection']['entries']:
                if i['type']=='folder':
                    subfolder_ids.append(i['id'])
                elif i['type']=='file':
                    total_file_count += 1

                subfolder = False if not subfolder_ids

    return total_file_count

2 个答案:

答案 0 :(得分:0)

这是使用while循环的一般方法。我们的想法是从文件夹ID列表开始(您以root身份提供),然后从您获得的条目中添加任何文件夹以搜索该列表。因此,虽然还有要检查的文件夹,但您会继续发出请求并添加文件计数。

def get_file_count(client, folder_id):
  count = 0
  folders = [folder_id]
  while len(folders) > 0:
    id = folders.pop(0)
    data = client.get_folder(id)
    entries = data["item_collection"]["entries"]
    for entry in entries:
      if entry["type"] == "folder":
        folders.append(entry["id"])
      else:
        count += 1    
  return count

您可能会也可能无法复制和粘贴它,但这仅用于说明目的。

理想情况下,如果有一个API可以同时为您提供所有条目,那就太好了,但我可以想象很多用例不可能,所以你必须一次又一次地提出请求单独

解决方案未经过优化。

答案 1 :(得分:0)

不确定我是否完全得到了用例,但这应该可行。 它将遵循一系列文件夹,直到到达仅文件的文件夹 然后退回到前一个父母并再次工作。递归结束 当函数尝试通过根节点进行备份时。

如果您在实施时遇到问题,请告诉我,如果没有完整的测试用例,我无法进行调试。

我根据你的例子做了一些假设,

1)id是简单的整数,严格来说是基数。

2)第一个目录的id为0 - 可以将其更改为其他整数

3)您只需查找文件计数。

如果其中一些不是真的,我可以尝试重写我的解决方案。但我希望这能让你从右脚开始。

def iterdir(client, root, viewed=list(), steps=0, filecount=0):
    if root < 0:
        return filecount
    else:
        folder = client.get_folder(root)
        viewed.append(root)
        subdirs = [int(item['id']) for item in folder['item_collection']['entries'] if item['type'] == 'folder' and int(item['id']) not in viewed]
        if len(subdirs) == 0:
            iterdir(client=client, root=root - 1, steps = steps - 1, viewed=viewed, 
                    filecount=filecount+len([item for item in folder['item_collection']['entries'] if item['type'] == 'file']))       
        else:
            nfiles = len(folder['item_collection']['entries']) - len(subdirs)
            iterdir(client=client,
                    root=subdirs.pop(),
                    steps = steps + 1,
                    viewed=viewed, filecount = filecount + nfiles)