代码之家  ›  专栏  ›  技术社区  ›  qshng

如何动态迭代子目录

  •  0
  • qshng  · 技术社区  · 6 年前

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

    这里的一个用例是,假设我有一个目录结构,可以包含未知的子目录层,我想得到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\u 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 回复  |  直到 6 年前
        1
  •  0
  •   MxLDevs    6 年前

    这里有一个使用while循环的通用方法。想法是从文件夹ID列表开始(作为根目录提供),然后从获得的条目中,添加要搜索的任何文件夹到该列表中。因此,虽然仍有文件夹需要检查,但您将不断发出请求并累积文件计数。

    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可以同时为您提供所有条目,那就太好了,但我可以想象很多情况下这是不可能的,因此您必须一次又一次地单独发出请求。

    解决方案未优化。

        2
  •  0
  •   Dan Temkin    6 年前

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

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

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

    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)