Python os.walk topdown与正则表达式一致

时间:2015-06-24 00:42:08

标签: python regex os.walk

我很困惑为什么以下仅适用于topdown=False并且设置为True时不返回任何内容?

我想使用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)

3 个答案:

答案 0 :(得分:1)

在你的代码中,你正在寻找匹配的名称([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

返回:

  

['根/ temp1目录/ myfiles的/ d12345678&#39 ;,
  '根/ temp1目录/ myfiles的/ m11111111&#39 ;,
  '根/ TEMP2 / mydirs / moredirs / m22222222&#39 ;,
  '根/ TEMP2 / mydirs / moredirs / p00000001']

答案 1 :(得分:1)

这是因为您的根目录与正则表达式不匹配,因此在第一次迭代后,dirs设置为空。

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

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

答案 2 :(得分:1)

问题是您在遍历时修改了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)

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