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!
需要检查一个目录,或者以特定目录为跟的目录树,对树中的每一个匹配的文件或目录进行操作.
讨论:
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!