首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用os.walk定位目录

用os.walk定位目录
EN

Stack Overflow用户
提问于 2016-11-02 16:34:50
回答 2查看 2K关注 0票数 4

由于目录结构庞大而复杂,我的脚本搜索了太多目录:

代码语言:javascript
复制
root--
     |
     --Project A--
                  |
                  -- Irrelevant
                  -- Irrelevant
                  -- TARGET
     |
     --Project B--
                  |
                  -- Irrelevant
                  -- TARGET
                  -- Irrelevant
     |
     -- Irrelevant  --
                       |
                       --- Irrelevant

目标目录是我唯一需要遍历的目录,它在每个项目中都有一个一致的名称(我们只在这里称它为TARGET )。

我看了这个问题:

Excluding directories in os.walk

但是不排除,我需要包括“目标”目录,它不是在“根”级别,而是向下一个级别。

我试过这样的方法:

代码语言:javascript
复制
def walker(path):
    for dirpath, dirnames, filenames in os.walk(path):
        dirnames[:] = set(['TARGET'])

但这一项会影响根目录(从而忽略它需要遍历的所有目录,项目A、项目B.)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-11-02 16:51:12

代码的问题是,您总是在修改dirnames列表,但这意味着即使在根级,所有子目录也会被删除,因此递归调用不会最终访问各种Project X目录。

您想要的是只在存在TARGET目录时清除其他目录:

代码语言:javascript
复制
if 'TARGET' in dirnames:
    dirnames[:] = ['TARGET']

这将允许os.walk调用访问Project X目录,但将阻止它进入Irrelevant目录。

票数 4
EN

Stack Overflow用户

发布于 2016-11-02 16:44:05

对于这样的白名单场景,我建议使用glob.iglob按模式获取目录。它是一个生成器,所以得到每个结果的速度和找到它们的速度一样快(注意:在编写本报告时,它仍然是用os.listdir实现的,而不是用os.scandir实现的,所以它只是一个生成器;每个目录都被急切地扫描,但是只有在从当前目录生成值之后,它才会扫描下一个目录)。例如,在本例中:

代码语言:javascript
复制
from future_builtins import filter  # Only on Py2 to get generator based filter

import os.path
import glob

from operator import methodcaller

try:
    from os import scandir       # Built-in on 3.5 and above
except ImportError:
    from scandir import scandir  # PyPI package on 3.4 and below

# If on 3.4+, use glob.escape for safety; before then, if path might contain glob
# special characters and you don't want them processed you need to escape manually
globpat = os.path.join(glob.escape(path), '*', 'TARGET')

# Find paths matching the pattern, filtering out non-directories as we go:
for targetdir in filter(os.path.isdir, glob.iglob(globpat)):
    # targetdir is the qualified name of a single directory matching the pattern,
    # so if you want to process the files in that directory, you can follow up with:
    for fileentry in filter(methodcaller('is_file'), scandir(targetdir)):
        # fileentry is a DirEntry with attributes for .name, .path, etc.

请参阅os.scandir上的文档以获得更高级的使用,或者只需对os.walk进行内部循环调用,以保留大部分原始代码。

如果您确实必须使用os.walk,那么您就可以更有针对性地修剪dirs。由于您指定了所有的TARGET目录应该只向下一个级别,这实际上是相当容易的。默认情况下,os.walk自上而下,这意味着第一组结果将是根目录(您不希望仅将其剪枝到TARGET条目)。所以你可以:

代码语言:javascript
复制
import fnmatch

for i, (dirpath, dirs, files) in enumerate(os.walk(path)):
    if i == 0:
        # Top level dir, prune non-Project dirs
        dirs[:] = fnmatch.filter(dirs, 'Project *')
    elif os.path.samefile(os.path.dirname(dirpath), path):
        # Second level dir, prune non-TARGET dirs
        dirs[:] = fnmatch.filter(dirs, 'TARGET')
    else:
        # Do whatever handling you'd normally do for files and directories
        # located under path/Project */TARGET/
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40385124

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档