目录
目录的操作
1.1 目录与文件操作函数
文件是由操作系统来管理的,并通过文件夹的方式来管理大量的文件。文件除了读写操作以外,还可以进行复制、移动、删除等操作。文件夹也可以进行创建、移动、获取文件等操作。Python中对文件、文件夹操作时,可以使用os模块或shutil模块,如下面的两个表格所示:
方法 | 功能描述 |
os.getcwd() | 得到当前工作目录,即当前Python脚本工作的目录路径 |
os.listdir(path) | 返回指定目录path下的所有文件和目录名 |
os.remove(filename) | 该方法用来删除一个文件,不能删除目录 |
os.removedirs(path) | 递归地删除多个目录,若目录没有成功删除,将抛出错误 |
os.rmdir(path) | 删除目录path,要求path必须是空目录,否则抛出OSError错误 |
os.path.isfile(path) | 检验给出的路径path是否是一个文件 |
os.path.isdir(path) | 检验给出的路径path是否是一个目录 |
os.path.isabs(path) | 判断path是否是绝对路径 |
os.path.exists(path) | 判断给出的路径path是否存在 |
os.path.split(path) | 把路径分割成路径名和文件名,返回一个元组 |
os.path.splitext(path) | 分割路径,返回路径名和文件扩展名的元组 |
os.path.dirname(path) | 返回文件的路径名 |
os.path.basename(path) | 返回文件名 |
os.path.getsize(path) | 返回文件大小,如果文件不存在,返回错误 |
os.rename(old,new) | 文件重命名 |
os.makedirs(path) | 创建多级目录 |
os.mkdir(path) | 创建单个目录 |
os.stat(file) | 获取文件属性 |
os.chmod(file) | 获取修改文件权限与时间戳 |
os.exit() | 终止当前进程 |
os.path.join(str1,str2) | 将多个路径组合后返回 |
方法 | 功能描述 |
shutil.copyfile(src,dst) | 从源src复制到dst中去。要求目标地址具备可写权限,且若dst存在,则覆盖 |
shutil.move(src,dst) | 移动文件或重命名 |
shutil.copymode(src,dst) | 仅复制权限,不更改文件内容、组和用户 |
shutil.copystat(src,dst) | 复制所有的状态信息,包括权限、组、用户、时间等 |
shutil.copy(src,dst) | 复制文件的内容以及权限,先copyfile再copymode |
shutil.copy2(src,dst) | 复制文件的内容以及文件的所有状态信息,先copyfile再copystat |
shutil.copytree(src,dst) | 递归地复制文件内容及状态信息 |
shutil.rmtree(path) | 递归地删除文件 |
shutil.move(src,dst) | 递归地移动文件 |
make_archive(base_name, format,root_dir=None,base_dir=None, verbose=0,dry_run=0,owner=None, group=None,logger=None) | 压缩打包: base_name:压缩打包后的文件名或路径名 format:压缩或者打包格式zip、tar、bztar或gztar root_dir:指定将哪个目录或文件打包(也就是源文件) |
shutil是一种高层次的文件操作工具,类似于高级API,其强大之处在于对文件的复制与删除操作很灵活。
编写一个Python程序,对于指定文件夹下的图片文件,按照用户给出的前缀和编码方式统一命名。
设计思路:用户输入文件后缀名和所在文件夹,查找是否存在这些文件,筛选文件夹下所有指定后缀的文件并存放到列表对象中。输出所有这些文件,询问用户是否重新命名。如果是,要求输入统一命名后的文件名前缀和数字编码位数,调用rename()方法对文件列表中的文件重命名,并输出命名结果。
程序为:
import os
#文件批量重命名函数
def imgRename():
#输入文件名后缀strip()方法用于删除多余的空格
ext=input('请输入要批量命名的文件后缀名:(如jpg、png等)。直接回车退出程序\n').strip()
if ext=='':
return #如果按enter键,退出函数
myPath=input('请输入图片文件所在文件夹:')
#获得指定文件夹下的所有文件信息并存入列表对象allFiles
allFiles=os.listdir(myPath)
ext_list=[] #ext_list用来存放指定后缀的文件,初值为空
list_len=[] #list_len用来存放文件名的长度,用于输出对齐
for ifile in allFiles:
#文件名和目录拼接成完整的路径
fullFile=os.path.join(myPath,ifile)
if os.path.isfile(fullFile) and os.path.splitext(ifile)[1][1:].lower()==ext:
#如果是文件且后缀为指定后缀,则添加到列表中
ext_list.append(ifile)
#每个文件名的长度添加到列表中
list_len.append(len(ifile))
if len(ext_list)==0:
print('未发现*.',ext,'类型的文件')
return
print('找到如下*.',ext,'文件:')
#遍历列表对象,输出指定文件夹下匹配后缀的所有文件名
for item in ext_list:
print(item)
print(25*'*') #连续打印25个*
choice=input('您确定要对这些文件批量重命名吗?\n(Y/y----确定,N/n----取消)')
if choice!='y' and choice!='Y':
return
else:
fi_num_cnt=1 #文件编号初始化为1
input_max_len=max(list_len) #获得文件名的最大长度
preFix=input('请输入文件前缀:') #输入数字编号之前的前缀
#输入编号位数
noSize=int(input('请输入编号宽度,如1表示编号为1,2,3……,3表示编号为001,002,003……'))
#输入重新命名目标文件夹
dstPath=input('请输入重命名后图片文件所在文件夹:')
for ifile in ext_list: #遍历列表,对每个文件重命名
#生成新文件名,其中,zfill()方法用于在数字前补零
new_name=preFix+str(fi_num_cnt).zfill(noSize)+'.'+ext
#如果新生成的文件名已存在,则增加编号,继续生成新文件名
while True:
if os.path.exists(os.path.join(dstPath,new_name)):
fi_num_cnt+=1
new_name=preFix+str(fi_num_cnt).zfill(noSize)+'.'+ext
else:
break
#输出新、旧文件名信息
print(ifile.rjust(input_max_len,' '),3*' ','重命名为:'.ljust(5,' '),new_name.rjust(10,' '))
try:
#调用rename()方法重新命名文件
os.rename(os.path.join(myPath,ifile),os.path.join(dstPath,new_name))
except Exception as e:
print(e)
fi_num_cnt+=1
print('运行结束!')
if __name__=='__main__':
imgRename()
运行结果为:
E:\PycharmProjects\PythonTest\venv\Scripts\python.exe E:/PycharmProjects/PythonTest/ssss.py python ssss.py 5 2
请输入要批量命名的文件后缀名:(如jpg、png等)。直接回车退出程序
jpg
请输入图片文件所在文件夹:C:\Users\Desktop\新建文件夹\汉口江滩
找到如下*. jpg 文件:
97820423A438CDEA70F63BC8F496582E.jpg
99E4EA6342F1AB16601C884EDA93094D.jpg
A9E206588A20CA06B4AA8B3AE07AE2F2.jpg
*************************
您确定要对这些文件批量重命名吗?
(Y/y----确定,N/n----取消)y
请输入文件前缀:mycat
请输入编号宽度,如1表示编号为1,2,3……,3表示编号为001,002,003……3
请输入重命名后图片文件所在文件夹:C:\Users\Desktop\新建文件夹\汉口江滩1
97820423A438CDEA70F63BC8F496582E.jpg 重命名为: mycat001.jpg
99E4EA6342F1AB16601C884EDA93094D.jpg 重命名为: mycat002.jpg
A9E206588A20CA06B4AA8B3AE07AE2F2.jpg 重命名为: mycat003.jpg
运行结束!
Process finished with exit code 0
1.2 目录的遍历
在文件操作中经常需要遍历某个文件夹或者子文件夹。在Python中进行文件遍历的方式很多,下面介绍几种常用的方式。
1.使用os.popen()方法运行命令
语法格式: os.popen(command[,mode[,bufsize]])
功能:用于从一个命令打开一个管道,在Unix、Windows中有效。返回一个文件描述符号为fd的打开的文件对象。
参数说明:
- command 使用的系统命令
- mode 模式权限,可以是r(默认)或w
- bufsize 指明文件需要的缓冲大小:0意味着无缓冲;1意味着行缓冲;其他正值表示使用参数大小的缓冲(大概值,以字节为单位)。负的bufsize意味着使用系统的默认值。一般来说,对于tty设备,它是行缓冲;对于其他文件,它是全缓冲。如果没有改参数,使用系统的默认值。
2.使用glob模块的glob(path)方法
语法格式: glob.glob(pathname)
功能:逐个获取匹配的文件路径名,返回所有匹配的文件路径列表
参数说明:
- pathname 定义了文件路径匹配规则,可以是绝对路径,也可以是相对路径
- 查找文件只用到3个匹配符 *、?和[]。*匹配0个或多个字符;?匹配单个字符;[]匹配指定范围内的字符
3.使用os.listdir()方法
详见上面的表格。
4.使用os.walk()方法
语法格式: os.walk(top[,topdown=True[,οnerrοr=None[,followlinks=False]]])
功能:通过在目录树中遍历,输出在目录中的文件名,可以向上或者向下。在Unix、Windows中有效。
参数说明:
- top 根目录下的每一个文件夹(包含它自己),产生一个三元组(dirpath,dirnames,filenames)[文件夹路径,文件夹名字,文件名]
- topdown 可选,为True或者没有指定,一个目录的三元组将比它的任何子文件夹的三元组先产生(目录自上而下)。如果topdown为False,一个目录的三元组将比它的任何子文件夹的三元组后产生(目录自下而上)
- onerror() 可选,是一个函数;调用时需要一个参数,一个OSError实例。报告错误后,继续walk,或者抛出exception终止walk。
- followlinks 设置为True,则通过软链接访问目录
不同遍历方式示例的程序代码如下:
import os
import glob
def listByShell(path):
for f in os.popen('dir '+path):
print(f.strip())
def listByGlob(path):
for f in glob.glob(path+'/*'):
print(f.strip())
def listByListdir(path):
for f in os.listdir(path):
print(f.strip())
def listByOSWalk(path):
for (dirname,subdir,subfile) in os.walk(path):
print('['+dirname+']')
for f in subfile:
print(os.path.join(dirname,f))
def main():
print('使用os.popen方法遍历:')
listByShell(r'e:\PycharmProjects')
print('使用glob,glob方法遍历:')
listByGlob(r'e:\PycharmProjects')
print('使用os.listdir方法遍历:')
listByListdir(r'e:\PycharmProjects')
print('使用os.walk方法遍历:')
listByOSWalk(r'e:\PycharmProjects')
main()
运行结果为:
E:\PycharmProjects\PythonTest\venv\Scripts\python.exe E:/PycharmProjects/PythonTest/ssss.py python ssss.py 5 2
使用os.popen方法遍历:
驱动器 E 中的卷没有标签。
卷的序列号是 C402-DAC5
e:\PycharmProjects 的目录
2019/07/18 10:47 <DIR> .
2019/07/18 10:47 <DIR> ..
2019/08/20 10:57 <DIR> PythonTest
2018/10/12 20:43 <DIR> test
0 个文件 0 字节
4 个目录 71,039,795,200 可用字节
使用glob.glob方法遍历:
e:\PycharmProjects\PythonTest
e:\PycharmProjects\test
使用os.listdir方法遍历:
PythonTest
test
使用os.walk方法遍历:
[e:\PycharmProjects]
[e:\PycharmProjects\PythonTest]
e:\PycharmProjects\PythonTest\modu1.py
e:\PycharmProjects\PythonTest\modu2.py
e:\PycharmProjects\PythonTest\muModu.py
e:\PycharmProjects\PythonTest\sample5_17.py
e:\PycharmProjects\PythonTest\sample5_18.py
e:\PycharmProjects\PythonTest\ssss.py
[e:\PycharmProjects\PythonTest\.idea]
e:\PycharmProjects\PythonTest\.idea\misc.xml
e:\PycharmProjects\PythonTest\.idea\modules.xml
e:\PycharmProjects\PythonTest\.idea\PythonTest.iml
e:\PycharmProjects\PythonTest\.idea\workspace.xml
Process finished with exit code 0
编写程序,遍历指定目录及所有子目录,将所有子目录名和文件名全部改为小写。
设计思路:根据题目要求,需要递归遍历文件夹下的所有文件及子文件夹。可以用os.work()方法完成,这样就不需要编写递归遍历程序。对方法的返回结果进行遍历。首先遍历所有文件,修改文件名全部为小写;然后遍历所有文件夹,修改所有文件夹的名字为小写。
程序如下:
import os
import os.path
#读入指定目录并转换为绝对路径
rootdir=input('请输入文件夹:')
#先从外向内依次修改每个目录下的文件名
#利用os.work()方法读入所有的文件夹和文件夹中的文件
#遍历每个文件夹,检测该文件夹的所有文件名并重命名
for (dirname,subdir,files) in os.walk(rootdir):
#遍历每个文件,检测该文件名是否符合要求
for file in files:
#文件名与目录名拼接成完整路径
pathfile=os.path.join(dirname,file)
#把文件名转换成小写字母
pathfileLower=os.path.join(dirname,file.lower())
#检测文件名是否是小写字母
if pathfile==pathfileLower:
continue
#打印转换前后的文件名
print(pathfile+'-->'+pathfileLower)
#调用rename()方法完成重命名操作
os.rename(pathfile,pathfileLower)
#然后,从内向外依次修改每个目录名
#参数topdown决定遍历的顺序,如果为True,从外向内;如果是False,从内向外
#以下循环结构用于由内向外遍历每个文件夹,检测该文件夹的名字并重命名
for (dirname,subdir,files) in os.walk(rootdir,topdown=False):
#遍历每个文件夹,检测该文件夹的名字是否符合要求
for dirs in subdir:
#文件夹名与目录名拼接成完整路径
pathdir=os.path.join(dirname,dirs)
pathdirLower=os.path.join(dirname,dirs.lower())
if pathdir==pathdirLower:
#如果文件夹名全是小写,检测下一个文件夹名
continue
print(pathdir+'-->'+pathdirLower)
#文件夹重命名
os.rename(pathdir,pathdirLower)
运行结果为:
E:\PycharmProjects\PythonTest\venv\Scripts\python.exe E:/PycharmProjects/PythonTest/ssss.py
请输入文件夹:E:\SHI
E:\SHI\SHI_1.txt-->E:\SHI\shi_1.txt
E:\SHI\SHI_2.txt-->E:\SHI\shi_2.txt
E:\SHI\TRY\TRY_1.txt-->E:\SHI\TRY\try_1.txt
E:\SHI\TRY\TRY_2.txt-->E:\SHI\TRY\try_2.txt
E:\SHI\TRY-->E:\SHI\try
Process finished with exit code 0