使用Python自下而上遍历目录树
我想找个方法,用Python从底部向上遍历一个文件夹树。我的目标是找到一个文件夹,它的位置可能在当前文件夹的上面或下面,具体距离不确定。
我画了个图,希望能让我的问题更清楚:
红色框是起点,绿色框是可能的目标文件夹位置,实际上只需要找到其中一个就可以了,不用两个都找。
如果目标文件夹是 /One/_One/_One,我希望脚本先往上走到 /One,然后再一路往下找到 /One/_One/_One。
如果目标文件夹是 /Three,我希望脚本也先做同样的事情,接着去 /Two 和 /Two/_Two,没找到后,最后到达 /Three。或者说,先检查完 /One 后,它会去根目录 /,然后找到 /Three,这样就跳过了 /Two 的遍历。
任何帮助都非常感谢。我一直在看 os.path 和 os.walk 的方法,但还没找到解决方案。
1 个回答
这个问题的关键在于关于 os.walk
的文档说明:
当设置为 True 时,调用者可以直接修改 dirnames 列表(比如用 del 或切片赋值),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'
目录,跳过 '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'。不过,你应该能很容易地找到修改搜索条件的方法来实现这一点。