【问题标题】:List directories with a specified depth in Python在 Python 中列出具有指定深度的目录
【发布时间】:2011-08-23 10:28:06
【问题描述】:

我想要一个函数来返回一个包含具有指定路径和固定深度的目录的列表,并很快意识到有一些替代方案。我经常使用 os.walk,但是在计算深度等时代码开始看起来很丑。

真正最“整洁”的实现是什么?

【问题讨论】:

    标签: python


    【解决方案1】:

    如果深度是固定的,glob 是个好主意:

    import glob,os.path
    filesDepth3 = glob.glob('*/*/*')
    dirsDepth3 = filter(lambda f: os.path.isdir(f), filesDepth3)
    

    否则,使用os.walk应该不会太难:

    import os,string
    path = '.'
    path = os.path.normpath(path)
    res = []
    for root,dirs,files in os.walk(path, topdown=True):
        depth = root[len(path) + len(os.path.sep):].count(os.path.sep)
        if depth == 2:
            # We're currently two directories in, so all subdirs have depth 3
            res += [os.path.join(root, d) for d in dirs]
            dirs[:] = [] # Don't recurse any deeper
    print(res)
    

    【讨论】:

    • 您使用 glob 的第一个示例非常棒,我永远不会走这条路。谢谢一百万!
    • 您可以在filesDepth3的定义中直接指定您的路径模式。如果您正在浏览大型文件夹数据库,则当前配置将花费很长时间。首先获取所有 3 级文件夹,然后按名称或内容过滤是次优资源使用。
    【解决方案2】:

    这并不完全整洁,但是在类UNIX操作系统下,你也可以依赖“find”之类的系统工具,将其作为外部程序执行,例如:

    from subprocess import call
    call(["find", "-maxdepth", "2", "-type", "d"])
    

    然后您可以将输出重定向到某个字符串变量以进行进一步处理。

    【讨论】:

    • 这将返回深度为 1 和 2 的目录。要仅获取深度为 2 的目录,必须将 "-mindepth","2" 添加到调用参数列表中。
    • 你也可以call("find -maxdepth 2 -mindepth 2 -type d", shell=True).
    【解决方案3】:

    使用os.scandir 的简单递归解决方案:

    def _walk(path, depth):
        """Recursively list files and directories up to a certain depth"""
        depth -= 1
        with os.scandir(path) as p:
            for entry in p:
                yield entry.path
                if entry.is_dir() and depth > 0:
                    yield from _walk(entry.path, depth)
    

    【讨论】:

      【解决方案4】:

      我真的很喜欢 phihag 的回答。我对其进行了调整以适应我的需要。

      import fnmatch,glob
      def fileNamesRetrieve( top, maxDepth, fnMask  ):
          someFiles = []
          for d in range( 1, maxDepth+1 ):
              maxGlob = "/".join( "*" * d )
              topGlob = os.path.join( top, maxGlob )
              allFiles = glob.glob( topGlob )
              someFiles.extend( [ f for f in allFiles if fnmatch.fnmatch( os.path.basename( f ), fnMask ) ] )
          return someFiles
      

      我想我也可以用这样的东西把它变成一个生成器:

      def fileNamesRetrieve( top, maxDepth, fnMask  ):
          for d in range( 1, maxDepth+1 ):
              maxGlob = "/".join( "*" * d )
              topGlob = os.path.join( top, maxGlob )
              allFiles = glob.glob( topGlob )
              if fnmatch.fnmatch( os.path.basename( f ), fnMask ):
                  yield f
      

      欢迎批评。

      【讨论】:

        【解决方案5】:

        这是一个简单的函数

        import os
        from glob import glob
        from pathlib import Path
        
        def find_sub_dirs(path, depth=2):
            path = Path(path)
            assert path.exists(), f'Path: {path} does not exist'
            depth_search = '*/' * depth
            search_pattern = os.path.join(path, depth_search)
            return list(glob(f'{search_pattern}'))
        

        【讨论】:

          猜你喜欢
          • 2023-03-26
          • 2012-04-17
          • 1970-01-01
          • 2018-02-19
          • 1970-01-01
          • 2014-04-03
          • 1970-01-01
          • 2017-03-20
          • 2015-08-21
          相关资源
          最近更新 更多