Python os.walk topdown true 正则表达式

Python os.walk topdown true with regular expression

我很困惑为什么以下设置为 True 时仅适用于 topdown=False 和 returns?

我想使用topdown=True的原因是遍历目录需要很长时间。我相信自上而下会增加生成列表所需的时间。

for root, dirs, files in os.walk(mypath, topdown=False): #Why doesn't this work with True?
    dirs[:] = [d for d in dirs if re.match('[DMP]\d{8}$', d)]
        for dir in dirs:
            print(dir)

在您的代码中,您正在寻找要遍历的匹配名称 ([dmp]\d{8}),而在将匹配名称添加到全局列表时,您应该寻找要遍历的不匹配目录。

我修改了你的代码,这有效:

import os
import re

all_dirs = []
for root, dirs, files in os.walk("root", topdown=True):
    subset = []
    for d in dirs:
        if not re.match('[dmp]\d{8}$', d):
            # step inside
            subset.append(d)
        else:
            # add to list
            all_dirs.append(os.path.join(root, d))
    dirs[:] = subset

print all_dirs

这个returns:

['root/temp1/myfiles/d12345678',
'root/temp1/myfiles/m11111111',
'root/temp2/mydirs/moredirs/m22222222',
'root/temp2/mydirs/moredirs/p00000001']

那是因为你的根目录与正则表达式不匹配,所以在第一次迭代后,dirs 被设置为空。

如果您想要查找与模式匹配的所有子目录,您应该:

  1. 使用 topdown = False,或者
  2. 不要修剪目录

问题是您在遍历时正在修改 dirs 的内容。使用 topdown=True 时,这将影响接下来遍历的目录。

看看这段代码,它向您展示了正在发生的事情:

import os, re

for root, dirs, files in os.walk("./", topdown=False):
    print("Walked down {}, dirs={}".format(root, dirs))
    dirs[:] = [d for d in dirs if re.match('[DMP]\d{8}$', d)]
    print("After filtering dirs is now: " + str(dirs))
    for dir in dirs:
        print(dir)

我只有一个目录要遍历 - Temp/MyFiles/D12345678(我在 Linux)。使用 topdown=False 上面产生这个输出:

Walked down ./Temp/MyFiles/D12345678, dirs=[]
After filtering dirs is now: []
Walked down ./Temp/MyFiles, dirs=['D12345678']
After filtering dirs is now: ['D12345678']
D12345678
Walked down ./Temp, dirs=['MyFiles']
After filtering dirs is now: []
Walked down ./, dirs=['Temp']
After filtering dirs is now: []

但是 topdown=True 我们得到这个:

Walked down ./, dirs=['Temp']
After filtering dirs is now: []

因为您要从 dirs 中删除所有子目录,所以您告诉 os.walk 您不想进一步遍历任何子目录,因此迭代停止。使用 topdown=False 时,dirs 的修改值不用于确定下一步要遍历的内容,因此它有效。

要修复它,请将 dirs[:] = 替换为 dirs =

import os, re

for root, dirs, files in os.walk("./", topdown=True):
    dirs = [d for d in dirs if re.match('[DMP]\d{8}$', d)]
    for dir in dirs:
        print(dir)

这给了我们:

D12345678

更新:

如果您完全确定某个目录不会包含您感兴趣的任何子目录,您可以在进一步遍历之前将它们从 dirs 中删除。例如,如果您知道“./Temp/MyDirs2”将 永远不会 包含任何您感兴趣的子目录,您可以在我们到达那里时清空 dirs 以加快速度:

import os, re

uninteresting_roots = { "./Temp/MyDirs2" }

for root, dirs, files in os.walk("./", topdown=True):
    if root in uninteresting_roots:
        # Empty dirs and end this iteration
        del dirs[:]
        continue
    dirs = [d for d in dirs if re.match('[DMP]\d{8}$', d)]
    for dir in dirs:
        print(dir)

除此之外,您无法知道哪些目录不需要遍历,因为要知道它们是否包含您必须遍历的有趣子目录。