+-
[Python]-10-文件读写(中)
首页 专栏 python 文章详情
0
头图

[Python]-10-文件读写(中)

发布于 5 月 5 日

引言

这篇文章介绍如何使用python的os与shutil模块,对文件或文件夹进行读写、创建、删除等操作。

文章目录

0×2.文件夹相关操作
a.拼接路径
b.获取子目录名
c.规范化路径输出
d.判断目录或文件是否存在
e.列出目录下所有文件
f.创建删除文件夹
g.通配符的使用
h.文件和文件夹重命名
i.文件夹复制

0×2.文件夹相关操作

a.拼接路径

os.path.join()函数用于拼接路径,它不会判断两个路径是否存在,仅仅完成将前面的路径和后面的路径进行拼接的功能,请看下面的实例:

#!/usr/bin/env python #coding=utf-8 import os path1="/www" path2="qingsword/com" print(os.path.join(path1,path2)) #输出 /www/qingsword/com

b.获取子目录名

有时候我们可能需要获取某个路径下最后一个子目录的名称,python提供了一个os.path.split()方法用于切割路径,请看下面的实例:

#!/usr/bin/env python #coding=utf-8 import os path1="/www/qingsword/com" #split()方法返回一个元组,包含两个元素,父路径和子目录名 print(os.path.split(path1)) #可以直接使用两个对象来接收元组中这两个元素 p1,p2=os.path.split(path1) print(p1) print(p2) #输出 ('/www/qingsword', 'com') /www/qingsword com

如果想递归获取路径中每一层目录的名称,可以使用下面的方法:

#!/usr/bin/env python #coding=utf-8 import os #------ def split_fully(path):     """递归获取路径中每一层目录的名称,返回一个元组"""     parent_path,dir_name=os.path.split(path)     if dir_name=="":         return (parent_path,)     else:         return split_fully(parent_path)+(dir_name,) path1="/www/qingsword/com" for p in split_fully(path1):     print(p) #输出 / www qingsword com

在上面这个实例中,程序的运行流程是这样的,split_fully()函数首先将"/www/qingsword/com"路径分割成"/www/qingsword"与"com",因为dir_name不为空,所以执行return split_fully(parent_path)+(dir_name,),这一句中(dir_name,)就相当于(com,)而前半段使用父路径再次调用函数本身,外层函数将被挂起等待split_fully(parent_path)结果的返回,这一次的调用parent_path="/www/qingsword";

第一次调用自身"/www/qingsword"被分割成"/www"和"qingsword",由于dir_name不为空,函数第二次调用自身,此时如果我们将所有变量都代入数据,返回最外层被挂起的函数查看return,应该是这样的结构return split_fully("/www")+(qingsword,)+(com,);

第二次调用自身,"/www"被分割成parent_path="/",dir_name="www"不为空,程序会第三次调用自身,这一次parent_path,dir_name=os.path.split(path)分割后,dir_name为空,所以返回parent_path="/",最后一层一层返回,最外层的结构就变成了return ("/",)+("www",)+("qingsword",)+("com",),只需要遍历这个元组,就能得到每个元素的值。

c.规范化路径输出

在路径中,"."表示当前目录,".."表示父目录,如果我们不希望这些符号出现,可以使用os.path.normpath()函数,它不仅可以规范路径,将两个点自动解析成父目录,还能去除路径中多余的斜杠,请看下面的实例:

#!/usr/bin/env python #coding=utf-8 import os path1="///www/./qingsword////hidden/..//com" print(os.path.normpath(path1)) #normpath会自动清除目录中多余的斜杠,并且将..解析为父目录,所以hidden目录后面的..就相当于在hidden目录里面执行了一个"cd .."命令,返回了qingsword目录中,而www目录后面的.就代表当前目录,所以直接去掉了,最后输出如下 /www/qingsword/com

d.判断目录或文件是否存在

os.path.exists()函数能够判断目标是否存在,但不能判断目标是文件还是目录,请看下面的实例:

#!/usr/bin/env python #coding=utf-8 import os path1="/www/qingsword/com" print(os.path.exists(path1)) print(os.path.exists("textfile")) #输出,如果目标存在就返回True,不存在就返回False TRUE FALSE

e.列出目录下所有文件

使用os.listdir()函数,可以返回目标目录下所有文件夹和文件的名称列表,请看下面的实例:

#!/usr/bin/env python #coding=utf-8 import os #获取当前脚本所在目录的绝对路径 file_path=os.path.abspath(".") #遍历列表,打印出每个文件或文件夹的名称 for name in os.listdir(file_path):     print(name) #如果想打印出目录下每个文件或文件夹的完整路径,可以修改print函数,下面两种方法效果相同 print(file_path+"/"+name) print(os.path.join(file_path,name))

如果想要对listdir的输出进行排序,可以使用sorted()函数,默认按照字母顺序排列,并且区分大小写,大写字母>符号>小写字母,这样for中的name会按照排序后的顺序读取并拼接:

#!/usr/bin/env python #coding=utf-8 import os file_path=os.path.abspath(".") #排序输出 for name in sorted(os.listdir(file_path)):     print(os.path.join(file_path,name))

上面的实例仅仅能够遍历某个目录下的文件和目录,但不能进行递归查询,也就是说,这个目录下的子目录中的文件是无法被搜索到的,下面提供一种遍历子目录文件的方法:

#!/usr/bin/env python #coding=utf-8 import os #------ def print_tree(path):     """递归目录"""     if os.path.isdir(path):         #遍历目录,打印绝对路径         for name in os.listdir(path):             abs_path=os.path.join(path,name)             print(abs_path)             #如果路径为目录,调用自身,打印子目录内容             if os.path.isdir(abs_path):                 print_tree(abs_path) print_tree("/home/qing/test")

再来看一个实例,读取目录下的文件,显示每个文件的绝对路径,大小和最后修改时间:

#!/usr/bin/env python #coding=utf-8 import os import time #------ def list_dir(path):     """打印目录中文件或文件夹的大小,最后修改时间和绝对路径"""     if os.path.isdir(path):         for name in os.listdir(path):             abs_path=os.path.join(path,name)             sz=os.path.getsize(abs_path)             modify_time=time.ctime(os.path.getmtime(abs_path))             print("Size:%-8d Last Modify Time:%-25s Path:%s"%(sz,modify_time,abs_path)) list_dir("/home/qing/test")

利用列表生成式可以很简洁的打印出某一类型的文件列表,例如:

#!/usr/bin/env python3 #coding=utf-8 import os #列出脚本所在文件夹中所有文件和文件夹名称 print([x for x in os.listdir(os.path.abspath("."))]) #列出脚本所在文件夹中所有子文件夹名称 print([x for x in os.listdir(os.path.abspath("."))\        if os.path.isdir(x)]) #列出脚本所在文件夹中所有py文件名称 print([x for x in os.listdir(os.path.abspath("."))\        if os.path.isfile(x) and os.path.splitext(x)[1]==".py"])

f.创建删除文件夹

创建文件夹:

#!/usr/bin/env python #coding=utf-8 import os #os.mkdir()函数一次只能创建一个文件夹 if not os.path.exists("qingsword"):     os.mkdir("qingsword") #os.makedirs()函数能够一次性递归创建多个文件夹 if os.path.isdir("qingsword"):     os.makedirs("qingsword/1/2/3/4")

Ps:在创建文件夹的过程中,如果目标存在,则会抛出一个"FileExistsError"异常。

删除文件夹:

#!/usr/bin/env python #coding=utf-8 import os import shutil if os.path.isdir("qingsword"):     os.rmdir("qingsword/1/2/3/4")     shutil.rmtree("qingsword")

Ps:os.rmdir()函数只能删除单个文件夹且文件夹下必须为空,否则会抛出一个"OSError"异常,而shutil模块的rmtree方法能够一次性删除目录及下面的所有文件。

g.通配符的使用

在python路径操作中,有下面这些比较常用的通配符:

匹配多个字符;

? 匹配单个字符;

[...] 匹配括号中的单个字符,可以指定多个字符或字符范围,例如:[ABCD]代表ABCD任意一个都能匹配;[a-z]匹配小写字母表中任意一个字符;[0-9]匹配0-9数字中的任意一个;

[!...]不匹配括号中指定的任意一个或某个范围中的一个;

在python中有一个通配符模块glob,这个模块的glob()函数同os.listdir()类似,都能返回某个目录下的文件,但glob.glob()函数更加强大,它能够配合通配符返回指定的文件类型,请看下面的实例:

#!/usr/bin/env python #coding=utf-8 import os import glob path1="/home/qing/test" if os.path.isdir(path1):     #返回path1目录下所有py后缀的文件     print(glob.glob(os.path.join(path1,"*.py")))     #返回文件名最后一个字符在a-d范围内的py文件     print(glob.glob(os.path.join(path1,"*[a-d].py")))     #返回文件名为四个字符的py文件     print(glob.glob(os.path.join(path1,"????.py")))     返回文件名为三个字符且最后一个字符不在b-f范围内的py文件     print(glob.glob(os.path.join(path1,"??[!b-f].py")))     #这是glob函数强大的地方,递归path1目录,返回目录以及子目录中所有py文件     print(glob.glob(os.path.join(path1,"*/*.py")))

Ps:glob.glob()函数返回类型为列表。

h.文件和文件夹重命名

os模块的rename方法可以实现文件和文件夹重命名的操作,请看下面的实例:

#!/usr/bin/env python3 #coding=utf-8 import os #如果file1存在且file2不存在,将file1改名为file2,file1可以是文件或文件夹的绝对或相对路径 if os.path.exists("file1") and not os.path.exists("file2"): os.rename("file1","file2")

i.文件夹复制

可以使用shutil模块的copytree方法来拷贝一个目录到目标位置,例如:

#!/usr/bin/env python3 #coding=utf-8 import os import shutil def copyDir(src,dst):     """完成源文件夹到目标位置的复制"""     if os.path.isdir(src) and not os.path.exists(dst):         shutil.copytree(src,dst)         print("复制成功。")     else:         print("复制失败。") def moveDir(src,dst):     """完成源文件夹到目标位置的移动"""     if os.path.isdir(src) and not os.path.exists(dst):         shutil.copytree(src,dst)         shutil.rmtree(src)         print("移动成功。")     else:         print("移动失败。")    moveDir("dir1","dir2") copyDir("dir1","dir2")
python 运维 linux ubuntu
阅读 37 发布于 5 月 5 日
举报
收藏
分享
本作品系原创, 采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议
avatar
1 声望
0 粉丝
关注作者
0 条评论
得票数 最新
提交评论
avatar
1 声望
0 粉丝
关注作者
宣传栏
目录

引言

这篇文章介绍如何使用python的os与shutil模块,对文件或文件夹进行读写、创建、删除等操作。

文章目录

0×2.文件夹相关操作
a.拼接路径
b.获取子目录名
c.规范化路径输出
d.判断目录或文件是否存在
e.列出目录下所有文件
f.创建删除文件夹
g.通配符的使用
h.文件和文件夹重命名
i.文件夹复制

0×2.文件夹相关操作

a.拼接路径

os.path.join()函数用于拼接路径,它不会判断两个路径是否存在,仅仅完成将前面的路径和后面的路径进行拼接的功能,请看下面的实例:

#!/usr/bin/env python #coding=utf-8 import os path1="/www" path2="qingsword/com" print(os.path.join(path1,path2)) #输出 /www/qingsword/com

b.获取子目录名

有时候我们可能需要获取某个路径下最后一个子目录的名称,python提供了一个os.path.split()方法用于切割路径,请看下面的实例:

#!/usr/bin/env python #coding=utf-8 import os path1="/www/qingsword/com" #split()方法返回一个元组,包含两个元素,父路径和子目录名 print(os.path.split(path1)) #可以直接使用两个对象来接收元组中这两个元素 p1,p2=os.path.split(path1) print(p1) print(p2) #输出 ('/www/qingsword', 'com') /www/qingsword com

如果想递归获取路径中每一层目录的名称,可以使用下面的方法:

#!/usr/bin/env python #coding=utf-8 import os #------ def split_fully(path):     """递归获取路径中每一层目录的名称,返回一个元组"""     parent_path,dir_name=os.path.split(path)     if dir_name=="":         return (parent_path,)     else:         return split_fully(parent_path)+(dir_name,) path1="/www/qingsword/com" for p in split_fully(path1):     print(p) #输出 / www qingsword com

在上面这个实例中,程序的运行流程是这样的,split_fully()函数首先将"/www/qingsword/com"路径分割成"/www/qingsword"与"com",因为dir_name不为空,所以执行return split_fully(parent_path)+(dir_name,),这一句中(dir_name,)就相当于(com,)而前半段使用父路径再次调用函数本身,外层函数将被挂起等待split_fully(parent_path)结果的返回,这一次的调用parent_path="/www/qingsword";

第一次调用自身"/www/qingsword"被分割成"/www"和"qingsword",由于dir_name不为空,函数第二次调用自身,此时如果我们将所有变量都代入数据,返回最外层被挂起的函数查看return,应该是这样的结构return split_fully("/www")+(qingsword,)+(com,);

第二次调用自身,"/www"被分割成parent_path="/",dir_name="www"不为空,程序会第三次调用自身,这一次parent_path,dir_name=os.path.split(path)分割后,dir_name为空,所以返回parent_path="/",最后一层一层返回,最外层的结构就变成了return ("/",)+("www",)+("qingsword",)+("com",),只需要遍历这个元组,就能得到每个元素的值。

c.规范化路径输出

在路径中,"."表示当前目录,".."表示父目录,如果我们不希望这些符号出现,可以使用os.path.normpath()函数,它不仅可以规范路径,将两个点自动解析成父目录,还能去除路径中多余的斜杠,请看下面的实例:

#!/usr/bin/env python #coding=utf-8 import os path1="///www/./qingsword////hidden/..//com" print(os.path.normpath(path1)) #normpath会自动清除目录中多余的斜杠,并且将..解析为父目录,所以hidden目录后面的..就相当于在hidden目录里面执行了一个"cd .."命令,返回了qingsword目录中,而www目录后面的.就代表当前目录,所以直接去掉了,最后输出如下 /www/qingsword/com

d.判断目录或文件是否存在

os.path.exists()函数能够判断目标是否存在,但不能判断目标是文件还是目录,请看下面的实例:

#!/usr/bin/env python #coding=utf-8 import os path1="/www/qingsword/com" print(os.path.exists(path1)) print(os.path.exists("textfile")) #输出,如果目标存在就返回True,不存在就返回False TRUE FALSE

e.列出目录下所有文件

使用os.listdir()函数,可以返回目标目录下所有文件夹和文件的名称列表,请看下面的实例:

#!/usr/bin/env python #coding=utf-8 import os #获取当前脚本所在目录的绝对路径 file_path=os.path.abspath(".") #遍历列表,打印出每个文件或文件夹的名称 for name in os.listdir(file_path):     print(name) #如果想打印出目录下每个文件或文件夹的完整路径,可以修改print函数,下面两种方法效果相同 print(file_path+"/"+name) print(os.path.join(file_path,name))

如果想要对listdir的输出进行排序,可以使用sorted()函数,默认按照字母顺序排列,并且区分大小写,大写字母>符号>小写字母,这样for中的name会按照排序后的顺序读取并拼接:

#!/usr/bin/env python #coding=utf-8 import os file_path=os.path.abspath(".") #排序输出 for name in sorted(os.listdir(file_path)):     print(os.path.join(file_path,name))

上面的实例仅仅能够遍历某个目录下的文件和目录,但不能进行递归查询,也就是说,这个目录下的子目录中的文件是无法被搜索到的,下面提供一种遍历子目录文件的方法:

#!/usr/bin/env python #coding=utf-8 import os #------ def print_tree(path):     """递归目录"""     if os.path.isdir(path):         #遍历目录,打印绝对路径         for name in os.listdir(path):             abs_path=os.path.join(path,name)             print(abs_path)             #如果路径为目录,调用自身,打印子目录内容             if os.path.isdir(abs_path):                 print_tree(abs_path) print_tree("/home/qing/test")

再来看一个实例,读取目录下的文件,显示每个文件的绝对路径,大小和最后修改时间:

#!/usr/bin/env python #coding=utf-8 import os import time #------ def list_dir(path):     """打印目录中文件或文件夹的大小,最后修改时间和绝对路径"""     if os.path.isdir(path):         for name in os.listdir(path):             abs_path=os.path.join(path,name)             sz=os.path.getsize(abs_path)             modify_time=time.ctime(os.path.getmtime(abs_path))             print("Size:%-8d Last Modify Time:%-25s Path:%s"%(sz,modify_time,abs_path)) list_dir("/home/qing/test")

利用列表生成式可以很简洁的打印出某一类型的文件列表,例如:

#!/usr/bin/env python3 #coding=utf-8 import os #列出脚本所在文件夹中所有文件和文件夹名称 print([x for x in os.listdir(os.path.abspath("."))]) #列出脚本所在文件夹中所有子文件夹名称 print([x for x in os.listdir(os.path.abspath("."))\        if os.path.isdir(x)]) #列出脚本所在文件夹中所有py文件名称 print([x for x in os.listdir(os.path.abspath("."))\        if os.path.isfile(x) and os.path.splitext(x)[1]==".py"])

f.创建删除文件夹

创建文件夹:

#!/usr/bin/env python #coding=utf-8 import os #os.mkdir()函数一次只能创建一个文件夹 if not os.path.exists("qingsword"):     os.mkdir("qingsword") #os.makedirs()函数能够一次性递归创建多个文件夹 if os.path.isdir("qingsword"):     os.makedirs("qingsword/1/2/3/4")

Ps:在创建文件夹的过程中,如果目标存在,则会抛出一个"FileExistsError"异常。

删除文件夹:

#!/usr/bin/env python #coding=utf-8 import os import shutil if os.path.isdir("qingsword"):     os.rmdir("qingsword/1/2/3/4")     shutil.rmtree("qingsword")

Ps:os.rmdir()函数只能删除单个文件夹且文件夹下必须为空,否则会抛出一个"OSError"异常,而shutil模块的rmtree方法能够一次性删除目录及下面的所有文件。

g.通配符的使用

在python路径操作中,有下面这些比较常用的通配符:

匹配多个字符;

? 匹配单个字符;

[...] 匹配括号中的单个字符,可以指定多个字符或字符范围,例如:[ABCD]代表ABCD任意一个都能匹配;[a-z]匹配小写字母表中任意一个字符;[0-9]匹配0-9数字中的任意一个;

[!...]不匹配括号中指定的任意一个或某个范围中的一个;

在python中有一个通配符模块glob,这个模块的glob()函数同os.listdir()类似,都能返回某个目录下的文件,但glob.glob()函数更加强大,它能够配合通配符返回指定的文件类型,请看下面的实例:

#!/usr/bin/env python #coding=utf-8 import os import glob path1="/home/qing/test" if os.path.isdir(path1):     #返回path1目录下所有py后缀的文件     print(glob.glob(os.path.join(path1,"*.py")))     #返回文件名最后一个字符在a-d范围内的py文件     print(glob.glob(os.path.join(path1,"*[a-d].py")))     #返回文件名为四个字符的py文件     print(glob.glob(os.path.join(path1,"????.py")))     返回文件名为三个字符且最后一个字符不在b-f范围内的py文件     print(glob.glob(os.path.join(path1,"??[!b-f].py")))     #这是glob函数强大的地方,递归path1目录,返回目录以及子目录中所有py文件     print(glob.glob(os.path.join(path1,"*/*.py")))

Ps:glob.glob()函数返回类型为列表。

h.文件和文件夹重命名

os模块的rename方法可以实现文件和文件夹重命名的操作,请看下面的实例:

#!/usr/bin/env python3 #coding=utf-8 import os #如果file1存在且file2不存在,将file1改名为file2,file1可以是文件或文件夹的绝对或相对路径 if os.path.exists("file1") and not os.path.exists("file2"): os.rename("file1","file2")

i.文件夹复制

可以使用shutil模块的copytree方法来拷贝一个目录到目标位置,例如:

#!/usr/bin/env python3 #coding=utf-8 import os import shutil def copyDir(src,dst):     """完成源文件夹到目标位置的复制"""     if os.path.isdir(src) and not os.path.exists(dst):         shutil.copytree(src,dst)         print("复制成功。")     else:         print("复制失败。") def moveDir(src,dst):     """完成源文件夹到目标位置的移动"""     if os.path.isdir(src) and not os.path.exists(dst):         shutil.copytree(src,dst)         shutil.rmtree(src)         print("移动成功。")     else:         print("移动失败。")    moveDir("dir1","dir2") copyDir("dir1","dir2")