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中使用swapCase()方法转换大小写的教程
May 20 Python
Python中的深拷贝和浅拷贝详解
Jun 03 Python
python如何实现excel数据添加到mongodb
Jul 30 Python
Python 3.6 性能测试框架Locust安装及使用方法(详解)
Oct 11 Python
python中将字典形式的数据循环插入Excel
Jan 16 Python
python实现隐马尔科夫模型HMM
Mar 25 Python
利用Python读取txt文档的方法讲解
Jun 23 Python
Python使用百度api做人脸对比的方法
Aug 28 Python
PHP统计代码行数的小代码
Sep 19 Python
爬虫代理池Python3WebSpider源代码测试过程解析
Dec 20 Python
python对数组进行排序,并输出排序后对应的索引值方式
Feb 28 Python
Matplotlib绘制条形图的方法你知道吗
Mar 21 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()警告的处理(date_default_timezone_set)
2013/10/22 PHP
PHP中in_array的隐式转换的解决方法
2018/03/06 PHP
Swoole实现异步投递task任务案例详解
2019/04/02 PHP
通过jQuery打造支持汉字,拼音,英文快速定位查询的超级select插件
2010/06/18 Javascript
原生Js与jquery的多组处理, 仅展开一个区块的折叠效果
2011/01/09 Javascript
jquery 设置元素相对于另一个元素的top值(实例代码)
2013/11/06 Javascript
纯JS代码实现隔行变色鼠标移入高亮
2016/11/23 Javascript
页面点击小红心js实现代码
2018/05/26 Javascript
详解Vue微信授权登录前后端分离较为优雅的解决方案
2018/06/29 Javascript
微信小程序实现列表页的点赞和取消点赞功能
2018/11/02 Javascript
electron踩坑之remote of undefined的解决
2020/10/06 Javascript
[10:07]2014DOTA2国际邀请赛 实拍选手现场观战DK对阵Titan
2014/07/12 DOTA
[02:51]2014DOTA2 TI小组赛总结中国军团全部进军钥匙球馆
2014/07/15 DOTA
[03:30]DOTA2完美“圣”典精彩集锦
2016/12/27 DOTA
python抓取网页中图片并保存到本地
2015/12/01 Python
numpy自动生成数组详解
2017/12/15 Python
Python 字符串换行的多种方式
2018/09/06 Python
python面向对象法实现图书管理系统
2019/04/19 Python
使用python socket分发大文件的实现方法
2019/07/08 Python
Django 项目重命名的实现步骤解析
2019/08/14 Python
python实现实时视频流播放代码实例
2020/01/11 Python
Python新手学习函数默认参数设置
2020/06/03 Python
python 线程的五个状态
2020/09/22 Python
使用css3做0.5px的细线的示例代码
2018/01/18 HTML / CSS
CSS3 实现穿梭星空动画
2020/11/13 HTML / CSS
html2canvas生成的图片偏移不完整的解决方法
2020/05/19 HTML / CSS
Html5之webcoekt播放JPEG图片流
2020/09/22 HTML / CSS
Max&Co官网:意大利年轻女性时尚品牌
2017/05/16 全球购物
Linux文件系统类型
2012/02/15 面试题
制药工程专业应届生求职信
2013/09/24 职场文书
建筑设计学生的自我评价
2014/01/16 职场文书
《燕子》教学反思
2014/02/18 职场文书
广告设计应届生求职信
2014/03/01 职场文书
css display table 自适应高度、宽度问题的解决
2021/05/07 HTML / CSS
Feign调用全局异常处理解决方案
2021/06/24 Java/Android
java如何实现获取客户端ip地址的示例代码
2022/04/07 Java/Android