Skip to main content
 首页 » 编程设计

python之使用 Python 自底向上遍历目录树

2025年05月04日15傻小

我想找到一种使用 Python 以自下而上的方式遍历目录树的方法。目标是找到一个位于当前目录之上或之下未知距离的目录。

我画了一张图,希望能让我的问题更清楚:

红色方框是起点,绿色方框是目标文件夹的可能位置,只需要找到一个,不需要同时找到两个。

如果目标框是/One/_One/_One,那么我希望脚本上升到/One,然后一直向下遍历到/One/_One/_One。

如果目标文件夹是/Three,那么我希望脚本执行与上面相同的操作,然后继续到/Two 和/Two/_Two,找不到它,然后最终到达/Three。或者,在检查完所有/One 之后,它将转到/,然后找到/Three,跳过/Two 的遍历。

如有任何帮助,我们将不胜感激。我一直在查看所有 os.path 和 os.walk 方法,但还没有找到我的解决方案。

请您参考如下方法:

关键在于以下关于 os.walk 的文档:

When topdown is True, the caller can modify the dirnames list in-place (perhaps using del or slice assignment), and walk() will only recurse into the subdirectories whose names remain in dirnames

考虑到这一点,您只需将此问题视为树搜索,从第一个节点的根开始,每次找不到解决方案时,您都会弹出一个级别并执行再次进行树搜索,到达那里时删除作为上次搜索根的节点。

假设我有以下内容:

start_path    = 'ABC0123/Comp/Scripts' 
searching_for ='Some_File' 

我可以做以下事情:

last_root    = start_path 
current_root = start_path 
found_path   = None 
while found_path is None and current_root: 
    pruned = False 
    for root, dirs, files in os.walk(current_root): 
        if not pruned: 
           try: 
              # Remove the part of the tree we already searched 
              del dirs[dirs.index(os.path.basename(last_root))] 
              pruned = True 
           except ValueError: 
              pass 
        if searching_for in files: 
           # found the file, stop 
           found_path = os.path.join(root, searching_for) 
           break 
     # Otherwise, pop up a level, search again 
     last_root    = current_root 
     current_root = os.path.dirname(last_root) 

第一次迭代应该搜索 'ABC0123/Comp/Scr​​ipts' 目录。然后,如果它没有找到 'Some_File',它将搜索 'ABC0123/Comp' 目录,跳过 'Scripts' 目录。然后它将搜索 'ABC0123' 目录,跳过 'Comp' 及其下的所有内容。

这是遍历的一些示例输出。 CR是current_root,LR是last_root,Exploring是 walk 的当前步骤中的 root。在这种情况下,文件位于 ABC0123/Paint/Output 中:

CR: 'ABC0123/Comp/Scripts/', LR: 'ABC0123/Comp/Scripts/' 
Exploring: 'ABC0123/Comp/Scripts/' 
CR: 'ABC0123/Comp/Scripts', LR: 'ABC0123/Comp/Scripts/' 
Exploring: 'ABC0123/Comp/Scripts' 
CR: 'ABC0123/Comp', LR: 'ABC0123/Comp/Scripts' 
Exploring: 'ABC0123/Comp' 
Exploring: 'ABC0123/Comp/Output' 
CR: 'ABC0123', LR: 'ABC0123/Comp' 
Exploring: 'ABC0123' 
Exploring: 'ABC0123/Lighting' 
Exploring: 'ABC0123/Lighting/Output' 
Exploring: 'ABC0123/Paint' 
Exploring: 'ABC0123/Paint/Output' 
 
>>> found_path 
'ABC0123/Paint/Output/Some_File' 

另请注意,您搜索的是目录还是文件并不是很清楚。我的代码假设是后者,但如果是前者,只需更改:

if searching_for in files: 

到

if searching_for in dirs: 

但请注意,在这两种情况下,都假设您正在搜索一个全局(在最大树深度内)唯一文件/目录,或者您遇到的该文件/目录的第一个实例就是那个您正在寻找。例如,正如所写,您无法专门搜索“Paint/Output”。但是,您应该能够很容易地弄清楚如何修改搜索条件以允许这样做。