2007-07-19

 

Python Cookbook 2.16 遍历目录树

需求:

需要检查一个目录,或者以特定目录为跟的目录树,对树中的每一个匹配的文件或目录进行操作.

讨论:

Python的标准模块os中提供的生成器os.walk就是为这个需求设计的.我们也可以封装它来实现自己的需求:

import os, fnmatch
def all_files(root, patterns='*', single_level=False, yield_folders=False):
    # Expand patterns from semicolon-separated string to list
    patterns = patterns.split(';')
    for path, subdirs, files in os.walk(root):
        if yield_folders:
            files.extend(subdirs)
        files.sort( )
        for name in files:
            for pattern in patterns:
                if fnmatch.fnmatch(name, pattern):
                    yield os.path.join(path, name)
                    break
        if single_level:
            break

标准库提供的os.walk是灵活 ,强大而且易用的.不过,正是因为它是标准的,所以它不够灵活,比如它不能选择特定类型的文件,或者以排序模式访问文件,或者只访问单层目录,而不是目录树等.本节演示了上述的功能如何添加到walk中,它将walk封装到自己写的生成器中,并使用标准库的fnmath来匹配特定类型的文件,如果要匹配多个类型,用分号分隔.
举例说明,你要获得/tmp目录下所有的Python和HTML文件,包括子目录,可以这样写:

thefiles = list(all_files('/tmp', '*.py;*.htm;*.html'))

如果你只是想一次一个的处理,可以不用构造一个列表,用循环就可以了:

for path in all_files('/tmp', '*.py;*.htm;*.html'):
    print path

如果你使用的平台对大小写敏感,你想使用大小写敏感的模式匹配,可以修改模式字符串,如:"*.[Hh][Tt][Mm][Ll]"而不是"*.html".

相关说明:

fnmatch(name, pat)
    Test whether FILENAME matches PATTERN.

    Patterns are Unix shell style:

    *       matches everything
    ?       matches any single character
    [seq]   matches any character in seq
    [!seq]  matches any char not in seq

    An initial period in FILENAME is not special.
    Both FILENAME and PATTERN are first case-normalized
    if the operating system requires it.
    If you don't want this, use fnmatchcase(FILENAME, PATTERN).

需要区别os.walk和os.path.walk!

Comments: 发表评论



<< Home

This page is powered by Blogger. Isn't yours?