2016-02-10 31 views
1

我需要递归处理目录树中的所有文件,但深度有限。Python 3 - 具有有限递归深度的旅行目录树

这意味着例如查找当前目录和前两个子目录级别中的文件,但没有进一步查找。在这种情况下,我必须处理./subdir1/subdir2/file,但不是./subdir1/subdir2/subdir3/file

我该如何在Python 3中做到最好?

目前我使用os.walk来处理所有文件备份到无限的深度在一个循环是这样的:

for root, dirnames, filenames in os.walk(args.directory): 
    for filename in filenames: 
     path = os.path.join(root, filename) 
     # do something with that file... 

我能想到的方式root计数目录分隔符(/)来确定当前文件的层次级别和break循环如果该级别超过所需的最大值。

我认为这种方法可能是不安全的,并且在需要忽略大量子目录时可能效率很低。这里最佳的方法是什么?

回答

3

我认为最简单和最稳定的方法是复制os.walkstraight out of the source的功能并插入您自己的深度控制参数。

import os 
import os.path as path 

def walk(top, topdown=True, onerror=None, followlinks=False, maxdepth=None): 
    islink, join, isdir = path.islink, path.join, path.isdir 

    try: 
     names = os.listdir(top) 
    except OSError, err: 
     if onerror is not None: 
      onerror(err) 
     return 

    dirs, nondirs = [], [] 
    for name in names: 
     if isdir(join(top, name)): 
      dirs.append(name) 
     else: 
      nondirs.append(name) 

    if topdown: 
     yield top, dirs, nondirs 

    if maxdepth is None or maxdepth > 1: 
     for name in dirs: 
      new_path = join(top, name) 
      if followlinks or not islink(new_path): 
       for x in walk(new_path, topdown, onerror, followlinks, None if maxdepth is None else maxdepth-1): 
        yield x 
    if not topdown: 
     yield top, dirs, nondirs 

for root, dirnames, filenames in walk(args.directory, maxdepth=2): 
    #... 

如果你没有兴趣在所有这些可选参数,你几乎可以大幅削减下来的功能:

import os 

def walk(top, maxdepth): 
    dirs, nondirs = [], [] 
    for name in os.listdir(top): 
     (dirs if os.path.isdir(os.path.join(top, name)) else nondirs).append(name) 
    yield top, dirs, nondirs 
    if maxdepth > 1: 
     for name in dirs: 
      for x in walk(os.path.join(top, name), maxdepth-1): 
       yield x 

for x in walk(".", 2): 
    print(x) 
+0

这是一个小问题,一个相当长的一段代码..如果可能的话,我更喜欢更紧凑的解决方案。我认为你的意思是......在步行(......)中:'在第二行而不是'os.walk'中,不是吗? –

+0

有趣的是,我只是撰写了一个较短的版本:-),而且你倒数第二行的错误“os.”是正确的。固定。 – Kevin

+0

这个短版看起来很酷。我修改它不返回目录(因为我只需要文件),并比较'if maxdepth!= 0',以便0表示仅表示当前目录,我可以使用负值传递整个目录结构。 –