1

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

我做了一个图表,希望能让我的问题更清楚: 目录树

红框是起点,绿框是目标文件夹的可能位置,只需要找到其中一个,而不是两个。

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

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

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

4

1 回答 1

7

关键在于以下文档os.walk

当 topdown 为 True 时,调用者可以就地修改 dirnames 列表(可能使用 del 或 slice 赋值),并且 walk() 只会递归到名称保留在 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/Scripts'目录。然后,如果没有找到'Some_File',它将搜索'ABC0123/Comp'目录,跳过“脚本”目录。然后它将搜索'ABC0123'目录,跳过'Comp'它下面的所有内容。

这是遍历的一些示例输出。CRis current_root, LRis last_root, and Exploringisroot的当前步骤中的walk。在这种情况下,文件位于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”。但是,您应该能够很容易地弄清楚如何修改搜索条件以允许这样做。

于 2014-08-01T14:18:54.150 回答