Python操作文件和目錄
讀寫(xiě)文件比較簡(jiǎn)單,有一點(diǎn)特別注意就好了
windows下Python默認(rèn)打開(kāi)的文件以gbk解碼,而一般我們的文件是utf-8編碼的惦辛,所以如果文本含有中文傀履,就會(huì)出現(xiàn)異常或者亂碼。此時(shí)手動(dòng)添加encoding='utf-8'
表示以u(píng)tf-8的方式打開(kāi)。
當(dāng)然Python寫(xiě)入時(shí)候,也是默認(rèn)以gbk的編碼寫(xiě)入导俘。而文件通常是utf-8格式保存的,所以若不指定寫(xiě)入的編碼方式剔蹋,一寫(xiě)入中文就是亂碼了
with open('abc.txt', encoding='utf-8') as f:
print(f.read()) # 這樣打開(kāi)文件有中文也不怕
# 當(dāng)然Python寫(xiě)入時(shí)候旅薄,默認(rèn)以gbk的編碼寫(xiě)入。而文件是utf-8格式保存的,所以不指定寫(xiě)入的編碼方式少梁,一寫(xiě)入中文就是亂碼了
with open('abc.txt', 'w', encoding='utf-8') as f:
f.write('你好')
好了進(jìn)入正題
os模塊
當(dāng)前工作目錄
下面的代碼可獲取/切換當(dāng)前工作目錄洛口,也就是.
代表的路徑
import os
print(os.getcwd()) # F:\PythonProject
os.chdir(r'D:\python')
print(os.getcwd()) # D:\python
print(os.path.abspath('.')) # D:\python
# 由于工作目錄切換到D:\python,所以這個(gè)aa.txt就在其下生成
with open('aa.txt', 'w', encoding='utf-8') as f:
f.write('你好')
os.chdir
可以切換當(dāng)前的工作目錄凯沪,也就是改變了.
所指向的目錄第焰。于是相對(duì)路徑aa.txt
就在切換后的路徑下生成。這兩個(gè)路徑表達(dá)同一個(gè)意思
aa.txt
.\aa.txt
還有兩個(gè)點(diǎn)妨马,表示當(dāng)前目錄的父目錄挺举。..\aa.txt
這樣就是D:\aa.txt
的意思了。
絕對(duì)路徑和相對(duì)路徑
- 絕對(duì)路徑指的是從根文件夾子(盤(pán)符)開(kāi)始
- 相對(duì)路徑是相對(duì)于當(dāng)前工作目錄
print(os.path.abspath('aa.txt')) # D:\python\aa.txt
print(os.path.isabs('aa.txt')) # False
print(os.path.isabs('.')) #False
上面的代碼烘跺,第一個(gè)函數(shù)返回參數(shù)路徑的絕對(duì)路徑湘纵,第二個(gè)函數(shù)用于檢查一個(gè)路徑是否是相對(duì)路徑。
獲取最后一個(gè)斜杠前后的路徑滤淳。
# 獲取最后一個(gè)斜杠后面的部分
print(os.path.basename(r'D:\python\aa.txt')) # aa.txt
print(os.path.dirname(r'D:\python\aa.txt')) # D:\python
# 當(dāng)然使用下面的函數(shù)可以同時(shí)獲得以上兩者
print(os.path.split(r'D:\python\aa.txt')) # ('D:\\python', 'aa.txt')
以其他方式分割
print(os.path.splitext(r'D:\python\aa.txt')) # ('D:\\python\\aa', '.txt')
print(os.path.splitdrive(r'D:\python\aa.txt')) # ('D:', '\\python\\aa.txt')
os.path.splitext
這個(gè)函數(shù)以可以方便地獲取文件后綴名瞻佛,如果提供地路徑是文件夾,那么返回空娇钱。
os.path.splitdrive
以盤(pán)符作為分隔。
注意绊困,它們都返回元組文搂。
檢查路徑
檢查一個(gè)路徑存不存在,是文件秤朗?還是文件夾煤蹭?
print(os.path.isfile('D:\python')) # False
print(os.path.isdir('D:\python')) # True
print(os.path.exists('D:\python')) # True
創(chuàng)建文件夾
os.mkdir('D:\good') # True 只能建立一級(jí)不存在的目錄,若已存在會(huì)報(bào)錯(cuò)
os.mkdir('D:\good\job') # True 注釋掉上一句取视,由于D:\good已經(jīng)存在硝皂,這里相當(dāng)于還是只新建了一級(jí)不存在的目錄
os.mkdir(r'D:\aa\bb') # 報(bào)錯(cuò)!作谭!由于aa和bb文件夾都不存在稽物,找不到D:\aa路徑,故不能創(chuàng)建
os.makedirs(r'D:\aa\bb') # 此函數(shù)沒(méi)有上上面的限制折欠,管他存不存在一股腦兒創(chuàng)建贝或,反正最后會(huì)生成此路徑就是了。不過(guò)如果此路徑已經(jīng)存在了锐秦,就會(huì)報(bào)錯(cuò)了
由此可以看出os.makedirs
更常用咪奖,可以創(chuàng)建處路徑里所有的文件夾。而os.mkdir
還必須保證上級(jí)目錄存在酱床,所以只能新建一級(jí)目錄羊赵。
連接路徑
print(os.path.join(r'D:\python', 'aa.txt')) # D:\python\aa.txt
這個(gè)函數(shù)也很常用,用于連接兩個(gè)路徑扇谣,組合成新路徑返回昧捷。
遍歷文件夾
# 返回元組闲昭,分別是當(dāng)前文件夾路徑, 當(dāng)前路徑下的子文件夾,當(dāng)前路徑下的文件
for current_path, subfolders, filesname in os.walk(r'D:\Cleaner'):
print(f'{current_path}\n{subfolders}\n{filesname}')
print('-'*30)
os.walk
可以遞歸遍歷給定路徑下所有地文件和文件夾料身√乐剑看下該目錄下這個(gè)函數(shù)會(huì)打印什么。這個(gè)函數(shù)會(huì)返回一個(gè)元組芹血,分別是(當(dāng)前路徑, 該路徑下的所有文件夾, 該路徑下的所有文件)贮泞,然后不斷遞歸深入,不斷返回這樣的元組幔烛。所以上面的for循環(huán)執(zhí)行了多次啃擦,直到路徑最深處。
D:\Cleaner
['CCleaner']
['desktop.ini']
------------------------------
D:\Cleaner\CCleaner
['Lang']
['branding.dll', 'business.dat', 'CCleaner.dat', 'CCleaner.exe', 'ccleaner.ini', 'CCleaner64.exe', 'portable.dat']
------------------------------
....
刪除文件/文件夾
# 永久刪除饿悬,不進(jìn)入回收站
os.remove(r'D:\aaaa.txt') # same as os.unlink()
# 目錄為空才能刪除, 只是刪除當(dāng)前文件夾
os.rmdir(r'D:\aaa\bbb\ccc\eee')
# 這個(gè)方法也不能刪除非空目錄令蛉,但是刪除了空文件夾子eee后若發(fā)現(xiàn)父級(jí)文佳夾也空就一并刪除
os.removedirs(r'D:\aaa\bbb\ccc\eee') # 剩下D:\aaa\bbb
# 強(qiáng)力,該目錄下所有文件/文件夾全部刪除狡恬,不管內(nèi)容空不空珠叔。慎用
shutil.rmtree(r'D:\aaa')
重命名
# 重命名文件夾,必須保證原路徑存在弟劲,目標(biāo)路徑不能已存在
os.rename(r'D:\python', 'D:\good')
# 重命名文件祷安,必須保證原路徑存在,目標(biāo)路徑不能已存在
os.rename(r'D:\good\aa.txt', r'D:\good\bb.txt')
# 上面都不能再目標(biāo)地址存在的情況下使用兔乞,這個(gè)函數(shù)粗暴汇鞭,如果目標(biāo)路徑已存在,則會(huì)覆蓋之庸追,慎用
os.replace(r'D:\good\bb.txt', r'D:\good\cc.txt')
獲取文件的大小
得到文件的大小霍骄,以字節(jié)為單位
print(os.path.getsize(r'D:\good\cc.txt'))
shutil模塊
os模塊的功能相當(dāng)強(qiáng)大,但是還有部分功能淡溯,比如復(fù)制/剪切文件和文件夾存在與shutil模塊中读整。
直接看代碼吧
copy
# 如果Movie目錄存在,則是把這個(gè)文件復(fù)制到了該目錄下血筑。
des1 = shutil.copy(r'D:\findall.txt', r'E:\Movie')
# 如果沒(méi)有該目錄绘沉,則新建Mov文件,無(wú)后綴名
des2= shutil.copy(r'D:\findall.txt', r'E:\Mov')
# 當(dāng)然指定了后綴名豺总,就把源文件復(fù)制過(guò)去并重命名
des2= shutil.copy(r'D:\findall.txt', r'E:\Mov.txt')
# copy只復(fù)制最后訪問(wèn)時(shí)間
des3 = shutil.copy(r'D:\findall.txt', r'E:\findit.txt')
# copy2同時(shí)拷貝所有元數(shù)據(jù)包括修改時(shí)間和最后訪問(wèn)時(shí)間
des4 = shutil.copy2(r'D:\findall.txt', r'E:\find.txt')
# 不拷貝訪問(wèn)時(shí)間和修改時(shí)間
des5 = shutil.copyfile(r'D:\findall.txt', r'E:\findaa.txt')
# 可以看到返回的是新文件所在的路徑
print(f'{des1}\n{des2}\n{des3}')
# 拷貝整個(gè)文件夾(里面所有內(nèi)容)到另外一個(gè)文件夾车伞,該文件夾不能是已經(jīng)存在的文件夾
shutil.copytree(r'D:\abc', r'E:\Movie')
move
# 剪切文件, abc不存在就移動(dòng)文件并改名為abc, abc目錄存在則放入該目錄
shutil.move(r'D:\findall.txt', r'E:\abc')
# 目標(biāo)地址若是文件,則是移動(dòng)并重命名
shutil.move(r'D:\findall.txt', r'E:\aa.txt')
# 剪切文件夾喻喳,如果目標(biāo)目錄已經(jīng)存在另玖,則剪切并放入該目錄,如果目標(biāo)目錄不存在,則相當(dāng)于移動(dòng)目錄到目標(biāo)地址并重命名文件夾
shutil.move(r'D:\abc', r'E:\avb')
ok谦去,對(duì)文件和目錄的操作也是日常生活中經(jīng)常會(huì)使用到的慷丽。學(xué)習(xí)了這些已經(jīng)可以自動(dòng)完成很多操作了。
by @sunhaiyu
2017.6.26