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中的自省(反射)详解
Jun 02 Python
基于Django的ModelForm组件(详解)
Dec 07 Python
一个月入门Python爬虫学习,轻松爬取大规模数据
Jan 03 Python
python使用turtle库与random库绘制雪花
Jun 22 Python
Django组件之cookie与session的使用方法
Jan 10 Python
djang常用查询SQL语句的使用代码
Feb 15 Python
关于pytorch多GPU训练实例与性能对比分析
Aug 19 Python
opencv python如何实现图像二值化
Feb 03 Python
python GUI库图形界面开发之PyQt5简单绘图板实例与代码分析
Mar 08 Python
django-利用session机制实现唯一登录的例子
Mar 16 Python
用 Python 制作地球仪的方法
Apr 24 Python
python用opencv 图像傅里叶变换
Jan 04 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
PHP中date与gmdate的区别及默认时区设置
2014/05/12 PHP
Laravel登录失败次数限制的实现方法
2020/08/26 PHP
js判读浏览器是否支持html5的canvas的代码
2013/11/18 Javascript
浅谈被jQuery抛弃的函数及替代函数
2015/05/03 Javascript
两种JS实现屏蔽鼠标右键的方法
2020/08/20 Javascript
js实现的全国省市二级联动下拉选择菜单完整实例
2015/08/17 Javascript
jQuery EasyUI 菜单与按钮之创建简单的菜单和链接按钮
2015/11/18 Javascript
jQuery实现淡入淡出的模态框
2017/02/09 Javascript
微信小程序左右滑动切换页面详解及实例代码
2017/02/28 Javascript
Vue2.0 从零开始_环境搭建操作步骤
2017/06/14 Javascript
浅谈原型对象的常用开发模式
2017/07/22 Javascript
jQuery实现广告条滚动效果
2017/08/22 jQuery
vue toggle做一个点击切换class(实例讲解)
2018/03/13 Javascript
详解如何搭建mpvue框架搭配vant组件库的小程序项目
2019/05/16 Javascript
javascript跳转与返回和刷新页面的实例代码
2019/11/20 Javascript
vscode 配置vue+vetur+eslint+prettier自动格式化功能
2020/03/23 Javascript
vue使用nprogress加载路由进度条的方法
2020/06/04 Javascript
浅谈vue获得后台数据无法显示到table上面的坑
2020/08/13 Javascript
[00:17]游戏风云独家报道:DD赛后说出数字秘密 吓死你们啊!
2014/07/13 DOTA
[01:04:09]DOTA2-DPC中国联赛 正赛 iG vs VG BO3 第二场 2月2日
2021/03/11 DOTA
通过代码实例展示Python中列表生成式的用法
2015/03/31 Python
python中验证码连通域分割的方法详解
2018/06/04 Python
Python利用ORM控制MongoDB(MongoEngine)的步骤全纪录
2018/09/13 Python
Tensorflow实现部分参数梯度更新操作
2020/01/23 Python
浅谈spring boot 集成 log4j 解决与logback冲突的问题
2020/02/20 Python
Python中zipfile压缩文件模块的基本使用教程
2020/06/14 Python
python 进程池pool使用详解
2020/10/15 Python
python自动化发送邮件实例讲解
2021/01/04 Python
FC-Moto美国:欧洲最大的摩托车服装和头盔商店之一
2019/08/24 全球购物
地理教师岗位职责
2014/03/16 职场文书
初中家长寄语
2014/04/02 职场文书
学生党员批评与自我批评
2014/10/15 职场文书
管理人员岗位职责
2015/02/14 职场文书
2015年发展党员工作总结报告
2015/03/31 职场文书
信用卡工作证明范本
2015/06/19 职场文书
一文弄懂MySQL索引创建原则
2022/02/28 MySQL