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 被设置为空。
如果您想要查找与模式匹配的所有子目录,您应该:
- 使用 topdown = False,或者
- 不要修剪目录
问题是您在遍历时正在修改 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)
除此之外,您无法知道哪些目录不需要遍历,因为要知道它们是否包含您必须遍历的有趣子目录。
我很困惑为什么以下设置为 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 被设置为空。
如果您想要查找与模式匹配的所有子目录,您应该:
- 使用 topdown = False,或者
- 不要修剪目录
问题是您在遍历时正在修改 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)
除此之外,您无法知道哪些目录不需要遍历,因为要知道它们是否包含您必须遍历的有趣子目录。