Python中的文件和目录操作实现代码


Posted in Python onMarch 13, 2011

本文将详细解释这些函数的使用方法。首先,我们介绍Python语言中类似于Windows系统的dir命令的列出文件功能,然后描述如何测试一个文件名对应的是一个标准文件、目录还是链接,以及提取文件大小和日期的方法。之后,我们还将介绍如何删除文件和目录,如何复制和删除文件,以及怎样将一个完整的文件路径分解成目录部分和文件名部分,最后,我们讲解目录的创建,以及如何在目录树中移动目录并处理文件。

一、显示目录内容

当我们想要列出当前目录中所有扩展名为.jpg或.gif的文件的时候,就可以使用glob模块来完成此项任务,如下所示:

import glob

filelist = glob.glob('*.jpg') + glob.glob('*.gif')

上述代码使用了glob函数,该函数的参数为要显示的文件类型。在这里,文件类型是通过类似UNIX操作系统shell风格通配符描述的一些文件名来指定的。这些通配符的使用方法,具体请参考fnmatch模块的文档,那里有具体的说明和示例。

为了显示一个目录中的全部文件,可以使用如下所示的os.listdir函数:

files = os.listdir(r'C:\hpl\scripting\src\py\intro') #适用于 Windows 

files = os.listdir('/home/hpl/scripting/src/py/intro') # 适用于Unix 

# 跨平台版本: 

files = os.listdir(os.path.join(os.environ['scripting'], 

'src', 'py', 'intro')) 

files = os.listdir(os.curdir) # 当前目录中的所有文件 

files = glob.glob('*') + glob.glob('.*')

二、测试文件类型

我们知道,文件名、目录名和链接名都是用一个字符串作为其标识符的,但是给我们一个标识符,我们该如何确定它所指的到底是常规文件文件名、目录名还是链接名呢?这时,我们可以使用os.path模块提供的isfile函数、isdir函数和islink函数来达成我们的目标,如下所示:

print myfile, '是一个', 
if os.path.isfile(myfile): 

print 'plain file' 

if os.path.isdir(myfile): 

print 'directory' 

if os.path.islink(myfile): 

print 'link'

您还可以查找文件的日期及其大小:

time_of_last_access = os.path.getatime(myfile) 

time_of_last_modification = os.path.getmtime(myfile) 

size = os.path.getsize(myfile)

这里的时间以秒为单位,并且从1970年1月1日开始算起。为了获取以天为单位的最后访问日期,可以使用下列代码:

import time # time.time()返回当前时间

age_in_days = (time.time()-time_of_last_access)/(60*60*24)

为了获取文件的详细信息,可以使用os.stat函数和stat模块中的其它实用程序来达到目的,如下:

import stat 

myfile_stat = os.stat(myfile) 

size = myfile_stat[stat.ST_SIZE] 

mode = myfile_stat[stat.ST_MODE] 

if stat.S_ISREG(mode): 

print '%(myfile)是一个常规文件,大小为 %(size)d 字节' %\ 

vars()

有关stat模块的详细信息,请参见Python Library Reference。若想测试一个文件的读、写以及执行权限,可以用os.access函数,具体如下所示:

if os.access(myfile, os.W_OK):

print myfile, '具有写权限'

if os.access(myfile, os.R_OK | os.W_OK | os.X_OK):

print myfile, '具有读、写以及执行权限'

像上面这样的测试代码,对CGI脚本来说非常有用。

三、文件和目录的删除

若要删除单个文件的话,可以使用os.remove函数,例如:os.remove('mydata.dat')。Os.remove的别名是os.unlink,不过后者跟传统的UNIX操作系统以及Perl中清除文件的函数重名。我们可以使用下列方式来删除一组文件,如所有以.jpg以及*.gif为扩展名的文件:

for file in glob.glob('*.jpg') + glob.glob('*.gif'):

os.remove(file)

大家知道,只有当目录中内容已经被清空的时候,我们才可以使用rmdir命令来删除该目录。不过,我们经常想要删除一个含有许多文件的目录树,这时我们可以使用shutil模块提供的rmtree函数,如下所示:

shutil.rmtree('mydir')

它相当于UNIX操作系统中的命令rm -rf mydir。

我们可以建立一个自定义函数,使其在进行删除操作的时候将文件和目录做同等对待,其典型用法如下所示:

remove('my.dat') #删除当个文件my.dat

remove('mytree') #删除单个目录树 mytree

# 通过字符串列表中的名称来删除多个文件/目录树:

remove(glob.glob('*.tmp') + glob.glob('*.temp'))

remove(['my.dat','mydir','yourdir'] + glob.glob('*.data'))

下面是remove函数的实现:

def remove(files):

"""删除一个或多个文件和/或目录。"""

if isinstance(files, str): # files是个字符串吗?

files = [files] # 把files从字符串转为列表

if not isinstance(files, list): # files不是列表吗?


for file in files:

if os.path.isdir(file):

shutil.rmtree(file)

elif os.path.isfile(file):

os.remove(file)

下面测试一下remove函数的灵活性:

# 建立10个目录tmp_* ,以及10各文件tmp__*: 

for i in range(10): 

os.mkdir('tmp_'+str(i)) 

f = open('tmp__'+str(i), 'w'); f.close() 

remove('tmp_1') # tmp_1为目录 

remove(glob.glob('tmp_[0-9]') + glob.glob('tmp__[0-9]'))

作为上述remove函数实现的一个注记,我们进行了下列测试:

if not isinstance(files, list):

它实际上是过于严厉。我们需要的只是一个被遍历的一个文件/目录名序列。实际上,我们并不关心名称是否存储在一个列表、元组或者数值数组中,所以更好的测试应该像下面这样:

if not operator.isSequenceType(files):


四、文件的复制与重命名

当我们要复制文件的时候,可以使用shutil模块:

import shutil

shutil.copy(myfile, tmpfile)

#拷贝最后访问时间和最后修改时间:

shutil.copy2(myfile, tmpfile)

# 拷贝一个目录树:

shutil.copytree(root_of_tree, destination_dir, True)

Copytree的第三个参数规定对符号链接的处理,其中True表示保留符号链接;而False则意味着使用文件的物理副本替代符号链接。

Python语言能够很好地支持路径名的跨平台组成:Os.path.join能使用正确的分界符(在UNIX和Mac OS X操作系统中使用/,在 Windows 上使用\)来联接目录和文件名,变量os.curdir和os.pardir分别表示当前工作目录及其父目录。 像下面的UNIX操作系统命令

cp https://3water.com/f1.c .

可以使用Python语言提供一个跨平台的实现:

shutil.copy(os.path.join(os.pardir,os.pardir,'f1.c'), os.curdir)

Os模块中的rename函数通常被用于重命名一个文件:

os.rename(myfile, 'tmp.1') # 将myfile重命名为'tmp.1'

这个函数也可用来在相同的文件系统之内移动文件。这里,我们将myfile移动到目录d下面:

os.rename(myfile, os.path.join(d, myfile))

在跨文件系统移动文件的时候,可以先使用shutil.copy2来复制文件,然后再删除原来的副本即可,如下:

shutil.copy2(myfile, os.path.join(d, myfile))

os.remove(myfile)

后面这种移动文件的方法是最安全的。

五、分解路径名

假设我们使用变量fname来存放一个包含完整路径的文件名,例如:

/usr/home/hpl/scripting/python/intro/hw.py

有时候,我们需要将这样的文件路径拆分为基本名称hw.py和目录名/usr/home/hpl/scripting/python/intro。在Python语言中,可以使用下列代码达到目的:

basename = os.path.basename(fname)

dirname = os.path.dirname(fname)

# 或

dirname, basename = os.path.split(fname)

扩展名是通过os.path.splitext函数提取出来的,

root, extension = os.path.splitext(fname)

这样,fname中的扩展名部分即.py被赋给变量extension,而其余部分则赋给了变量root。如果想得到不带点号的扩展名的话,只需使用os.path.splitext(fname)[1][1:]即可。

假设一个文件名为f,其扩展名随意,若想将其扩展名改为ext,可以使用下面的代码:

newfile = os.path.splitext(f)[0] + ext

下面是一个具体的示例:

>>> f = '/some/path/case2.data_source'

>>> moviefile = os.path.basename(os.path.splitext(f)[0] + '.mpg')

>>> moviefile

'case2.mpg'

六、目录的创建和移动

Os模块中的函数mkdir可以用来创建目录,而chdir函数则可以移动目录,如下:

origdir = os.getcwd() # 将当前位置记下来

newdir = os.path.join(os.pardir, 'mynewdir')

if not os.path.isdir(newdir):

os.mkdir(newdir) # 或者os.mkdir(newdir,'0755')

os.chdir(newdir)

...

os.chdir(origdir) # 返回原目录

os.chdir(os.environ['HOME']) # 移到主目录

假设我们想要在自己的主目录下创建一个新目录py/src/test1,但是目前py、src和test1都不存在。如果使用mkdir命令来创建的话,需要使用三次才能建好这个嵌套的目录,但是使用Python语言提供的os.makedirs命令的话,则无需这样麻烦了,该命令可以一次建好整个目录:

os.makedirs(os.path.join(os.environ['HOME'],'py','src','test1'))

七、遍历目录树

下面的函数调用

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)


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平台上,它们的使用方式是完全一致的。本文详细解释了这些函数的使用方法,其中,我们首先介绍了显示目录内容的功能,然后描述如何测试一个文件名对应的是一个标准文件、目录还是链接,以及提取文件大小和日期的方法。之后,我们还将介绍如何删除文件和目录,如何复制和删除文件,以及怎样将一个完整的文件路径分解成目录部分和文件名部分,最后,我们讲解目录的创建,以及如何在目录树中移动目录并处理文件。

Python 相关文章推荐
学习python的几条建议分享
Feb 10 Python
Python读取ini文件、操作mysql、发送邮件实例
Jan 01 Python
Python时间获取及转换知识汇总
Jan 11 Python
利用python实现xml与数据库读取转换的方法
Jun 17 Python
Django 忘记管理员或忘记管理员密码 重设登录密码的方法
May 30 Python
python+splinter实现12306网站刷票并自动购票流程
Sep 25 Python
详解python3安装pillow后报错没有pillow模块以及没有PIL模块问题解决
Apr 17 Python
python通过实例讲解反射机制
Oct 17 Python
详解Python可视化神器Yellowbrick使用
Nov 11 Python
wxPython窗体拆分布局基础组件
Nov 19 Python
PyQT5 实现快捷键复制表格数据的方法示例
Jun 19 Python
Python Pygame实战在打砖块游戏的实现
Mar 17 Python
python 中的列表解析和生成表达式
Mar 10 #Python
Python中使用中文的方法
Feb 19 #Python
python实现的防DDoS脚本
Feb 08 #Python
Python牛刀小试密码爆破
Feb 03 #Python
初学python数组的处理代码
Jan 04 #Python
让python json encode datetime类型
Dec 28 #Python
让python的Cookie.py模块支持冒号做key的方法
Dec 28 #Python
You might like
JS 网站性能优化笔记
2011/05/24 PHP
php检查页面是否被百度收录
2015/10/28 PHP
Laravel使用scout集成elasticsearch做全文搜索的实现方法
2018/11/30 PHP
jQuery动态地获取系统时间实现代码
2013/05/24 Javascript
jquery 扑捉回车键事件代码
2014/04/24 Javascript
js重写alert控件(适合学习js的新手朋友)
2014/08/24 Javascript
JavaScript实现仿新浪微博大厅和腾讯微博首页滚动特效源码
2015/09/15 Javascript
轻量级jQuery插件slideBox实现带底栏轮播(焦点图)代码
2016/03/28 Javascript
php简单数据库操作类的封装
2017/06/08 Javascript
JavaScript继承定义与用法实践分析
2018/05/28 Javascript
如何把vuejs打包出来的文件整合到springboot里
2018/07/26 Javascript
详解小程序rich-text对富文本支持方案
2018/11/28 Javascript
jQuery选择器选中最后一个元素,倒数第二个元素操作示例
2018/12/10 jQuery
Nuxt.js实战和配置详解
2019/08/05 Javascript
electron-vue开发环境内存泄漏问题汇总
2019/10/10 Javascript
Vue 用Vant实现时间选择器的示例代码
2019/10/25 Javascript
vue实现将数据存入vuex中以及从vuex中取出数据
2019/11/08 Javascript
Python运行的17个时新手常见错误小结
2012/08/07 Python
Python基于DES算法加密解密实例
2015/06/03 Python
Python访问纯真IP数据库脚本分享
2015/06/29 Python
wxpython中Textctrl回车事件无效的解决方法
2016/07/21 Python
python递归查询菜单并转换成json实例
2017/03/27 Python
python通过elixir包操作mysql数据库实例代码
2018/01/31 Python
如何安装多版本python python2和python3共存以及pip共存
2018/09/18 Python
Python猴子补丁Monkey Patch用法实例解析
2020/03/23 Python
python中round函数如何使用
2020/06/19 Python
pycharm配置python 设置pip安装源为豆瓣源
2021/02/05 Python
Java基础知识面试题
2014/03/25 面试题
Java面向对象面试题
2016/12/26 面试题
2014年超市员工工作总结
2014/11/18 职场文书
老公出轨后的保证书
2015/05/08 职场文书
军训后的感想
2015/08/07 职场文书
学习杨善洲同志先进事迹心得体会
2016/01/23 职场文书
如何才能写好调研报告?
2019/07/03 职场文书
Java后台生成图片的完整步骤
2021/08/04 Java/Android
Centos系统通过Docker安装并搭建MongoDB数据库
2022/04/12 MongoDB