技术开发 频道

Python中的文件和目录操作

  七、遍历目录树

  下面的函数调用

os.path.walk(root, myfunc, arg)

  将遍历root目录树;然后,对每个目录名dirname分别调用myfunc(arg, dirname, files)即可,这里参数files是dir中的文件名列表(可通过调用os.listdir(dirname)来获得);arg是用户从调用代码中传递来的参数。对于UNIX操作系统用户来说,Python语言中跨平台的os.path.walk相当于Unix命令find。

  在解释os.path.walk的用法的时候,人们常使用写出主目录中所有子目录内的文件的名称为例进行说明。当然,我们也可以在一个交互式的Python命令行中使用下列代码段来体会os.path.walk的使用:

  def ls(arg, dirname, files):

  
print dirname, ’has the files’, files

  os.path.walk(os.environ[’HOME’], ls, None)

  本例中,参数arg并非必需,所以在os.path.walk调用中让其取值为None即可。

  为了列出主目录中所有大于1Mb的文件,可以使用下面的代码:

  def checksize1(arg, dirname, files):

  
for file in files:

  filepath
= os.path.join(dirname, file)

  
if os.path.isfile(filepath):

  size
= os.path.getsize(filepath)

  
if size > 1000000:

  size_in_Mb
= size/1000000.0

  arg.append((size_in_Mb, filename))

  bigfiles
= []

  root
= os.environ[’HOME’]

  os.path.walk(root, checksize1, bigfiles)

  
for size, name in bigfiles:

  
print name, ’大小为’, size, ’Mb’

  现在,我们使用arg来建立一个数据结构,这里是一个2元组构成的列表,其中每个2元组存放文件的尺寸(以MB为单位)和完整的文件路径。如果用于所有目录的函数调用中都要更改arg的话,那么arg必须是一个可变的数据结构,即允许适当地进行修改。

  参数dirname是当前正在访问的目录的绝对路径,而参数files内的文件名则是相对于dirname的相对路径。在此期间,当前工作目录并没有改变,那就是说该脚本仍然呆在脚本启动时刻所在的目录中。这就是为什么我们需要把filepath弄成带有dirname和file的绝对路径的原因。若要改变当前工作目录为dirname,只要在针对每个目录调用os.path.walk的函数中调用一下os.chdir(dirname),然后在该函数的末尾重新调用os.chdir(dirname)将当前工作目录改回原值即可,如下所示:

def somefunc(arg, dirname, files):
origdir
= os.getcwd(); os.chdir(dirname)
<do tasks>
os.chdir(origdir)
os.path.walk(root, somefunc, arg)

  当然,如果您愿意也可以编写具有类似功能的代码来替代os.path.walk。下面的代码,将针对每个文件而非每个目录来调用的自定义函数,如下所示:

def find(func, rootdir, arg=None):
# 对rootdir目录中的每个文件调用func
files = os.listdir(rootdir) # 获取rootdir目录中的所有文件
files.sort(lambda a, b: cmp(a.lower(), b.lower()))
for file in files:
fullpath
= os.path.join(rootdir, file)
if os.path.islink(fullpath):
pass
elif os.path.isdir(fullpath):
find(func, fullpath, arg)
elif os.path.isfile(fullpath):
func(fullpath, arg)
else:
print ’find: cannot treat ’, fullpath

  上面的函数find可以从scitools模块中获取。与内置函数os.path.walk相反,我们的find函数以大小写敏感的字母顺序来访问文件和目录。

  我们可以使用find函数来列出所有大于1Mb的文件:

  def checksize2(fullpath, bigfiles):

  size
= os.path.getsize(fullpath)

  
if size > 1000000:

  bigfiles.append(’
%.2fMb %s’ % (size/1000000.0, fullpath))

  bigfiles
= []

  root
= os.environ[’HOME’]

  find(checksize2, root, bigfiles)

  
for fileinfo in bigfiles:

  
print fileinfo

  参数arg带来了巨大的灵活性。我们可以使用它来同时存放输入数据和生成的数据结构。下一个范例将收集所有大于一定尺寸的带有规定扩展名的文件的文件名和大小。输出的结果按照文件大小排列。

bigfiles = {’filelist’: [], # 文件名和大小列表
’extensions’: (’.*ps’, ’.tiff’, ’.bmp’),
’size_limit’:
1000000, # 1 Mb
}
find(checksize3, os.environ[’HOME’], bigfiles)
def checksize3(fullpath, arg):
treat_file
= False
ext
= os.path.splitext(fullpath)[1]
import fnmatch # Unix的shell风格的通配符匹配
for s in arg[’extensions’]:
if fnmatch.fnmatch(ext, s):
treat_file
= True # fullpath带有正确的扩展名
size = os.path.getsize(fullpath)
if treat_file and size > arg[’size_limit’]:
size
=%.2fMb’ % (size/1000000.0) # 打印
arg[’filelist’].append({’size’: size, ’name’: fullpath})
# 按照大小排列文件
def filesort(a, b):
return cmp(float(a[’size’][:-2]), float(b[’size’][:-2]))
bigfiles[’filelist’].sort(filesort)
bigfiles[’filelist’].reverse()
for fileinfo in bigfiles[’filelist’]:
print fileinfo[’name’], fileinfo[’size’]

  注意为列表排序的函数,bigfiles[’filelist’]函数中的每个元素就是一个字典,键size保存着一个字符串,不过在进行比较之前我们必须将单位Mb(最后两个字符)去掉,并将其转换为浮点数。

  八、小结

  对于文件和目录的处理,虽然可以通过操作系统命令来完成,但是Python语言为了便于开发人员以编程的方式处理相关工作,提供了许多处理文件和目录的内置函数。重要的是,这些函数无论是在Unix、Windows还是Macintosh平台上,它们的使用方式是完全一致的。本文详细解释了这些函数的使用方法,其中,我们首先介绍了显示目录内容的功能,然后描述如何测试一个文件名对应的是一个标准文件、目录还是链接,以及提取文件大小和日期的方法。之后,我们还将介绍如何删除文件和目录,如何复制和删除文件,以及怎样将一个完整的文件路径分解成目录部分和文件名部分,最后,我们讲解目录的创建,以及如何在目录树中移动目录并处理文件。

0
相关文章