os子產品
os子產品負責程式與作業系統的互動,提供了通路作業系統底層的接口;即os子產品提供了非常豐富的方法用來處理檔案和目錄。
使用的時候需要導入該子產品:import os
常用方法如下:
方法名 | 作用 |
os.remove(‘path/filename’) | 删除檔案 |
os.rename(oldname, newname) | 重命名檔案 |
os.walk() | 生成目錄樹下的所有檔案名 |
os.chdir('dirname') | 改變目錄 |
os.mkdir/makedirs('dirname') | 建立目錄/多層目錄 |
os.rmdir/removedirs('dirname') | 删除目錄/多層目錄 |
os.listdir('dirname') | 列出指定目錄的檔案 |
os.scandir() | 和listdir相近的功能,列出指定目錄的檔案 Python 官方推薦 |
os.getcwd() | 取得目前工作目錄 |
os.chmod() | 改變目錄權限 |
os.path.basename(‘path/filename’) | 去掉目錄路徑,傳回檔案名 |
os.path.dirname(‘path/filename’) | 去掉檔案名,傳回目錄路徑 |
os.path.join(path1[,path2[,...]]) | 将分離的各部分組合成一個路徑名 |
os.path.split('path') | 傳回( dirname(), basename())元組 |
os.path.splitext() | 傳回 (filename, extension) 元組 |
os.path.getatime\ctime\mtime | 分别傳回最近通路、建立、修改時間 |
os.path.getsize() | 傳回檔案大小 |
os.path.exists() | 是否存在 |
os.path.isabs() | 是否為絕對路徑 |
os.path.isdir() | 是否為目錄 |
os.path.isfile() | 是否為檔案 |
周遊所有檔案及檔案夾
獲得目前python程式運作路徑
import os
print(os.getcwd()) # 輸出目前代碼所在子產品的路徑
#
/Users/running/PycharmProjects/chapter04/novel
切換目錄到chapter03項目下:
os.chdir('/Users/running/PycharmProjects/chapter03')
檢視目前目錄下的所有檔案和檔案夾,并判斷是否是檔案和檔案夾
import os
files = os.listdir()
for file in files:
print(file, os.path.isdir(file),
os.path.isfile(file))
輸出結果:
或者使用:
for file in os.scandir():
print(file.name, file.path,
file.is_dir())
可以調用file.stat()擷取更加詳細的檔案資訊。如:
其中:
st_size:檔案的體積大小(機關:bytes),除以1024就是KB
st_atime:檔案的最近通路時間
st_mtime:檔案的最近修改時間
st_ctime:Windows下表示建立時間
案例1:
1. 鍵盤輸入一個路徑
2. 統計該路徑下的檔案和檔案夾,以及分别的數量
3. 統計目前路徑下包含檔案名稱中包含demo的檔案數量,注意不區分大小寫
import os
path = input('輸入要查詢的路徑:')
os.chdir(path)
file_list = []
dir_list = []
for file in os.scandir():
if file.is_dir():
dir_list.append(file.name)
else:
file_list.append(file.name)
print("檔案夾的總量是{},\n檔案為别為{}".format(len(dir_list),dir_list))
print('{}'.format('-'*30))
print("檔案總量是{},\n檔案為别為{}".format(len(file_list),file_list))
print('{}'.format('-'*30))
python_list = []
for name in file_list:
if 'demo' in name.lower():
python_list.append(name)
print('含有python單詞的檔案數量有{}個,\n檔案分别為{}'.format(len(python_list),python_list))
如果要周遊一個目錄下的所有子目錄,裡面指定的檔案,我們可以通過遞歸函數周遊每個目錄進行查找或者使用os.walk(),遞歸實作代碼如下:
import os
import sys
from stat import *
def walktree(top, callback):
for f in os.listdir(top):
pathname = os.path.join(top, f)
try:
mode = os.stat(pathname, follow_symlinks=False).st_mode
except:
continue
if S_ISDIR(mode):
# directory, recurse into it
walktree(pathname, callback)
else:
# file, whatever type, make the call back function
callback(pathname)
return
def printfile(file):
print('get to', file)
if __name__ == '__main__':
if (os.path.isabs(sys.argv[1]) and
os.path.exists(sys.argv[1])):
walktree(sys.argv[1], printfile)
Python os子產品的walk()函數,顧名思義,就是用來周遊目錄樹的,此函數可以很友善的周遊以輸入的路徑為root的所有子目錄和其中的檔案。
walk函數是一個Python生成器(generator),調用方式是在一個for...in...循環中,walk生成器每次傳回的是一個含有3個元素的tuple,分别是 (dirpath, dirnames, filenames)
for dirpath, dirnames, files in os.walk('./'):
print(dirpath,dirnames,files)
當然也可以使用glob子產品快速實作,假設要擷取主目錄中所有的mp4檔案:
此時使用glob更加友善
import glob
t_list = glob.glob('t*')
print(t_list) # 擷取目前目錄下t開頭的檔案,但是不能擷取子檔案夾裡面的内容
Python的glob還支援**規則(從3.5開始),當**規則與另一個參數recursive=True配合的時候,可以深入的路徑的子目錄當中去比對:
glob.glob('**') # 擷取目前目錄的檔案和檔案夾
glob.glob('**/') # 擷取目前目錄的檔案夾
# 如果**結合recursive=True使用,但是如果結合一個*則不能實作遞歸
glob.glob('**/',recursive=True) # 可以周遊出所有的子目錄
# 若要擷取子目錄中的檔案則需要
glob.glob('**/*.mp4',recursive=True)
案例2:
1. 鍵盤輸入一個路徑
2. 搜尋該路徑下檔案大小超過50M的zip檔案
3. 搜尋該路徑下最後修改日期在30天前的檔案
4. 列印顯示2,3的檔案
import os
import datetime
path = input('輸入要查詢的路徑:')
os.chdir(path)
paths = glob.glob('**/*.zip',recursive = True)
for path in paths:
file_size = os.stat(path).st_size/1024/1024
file_modify = datetime.datetime.fromtimestamp(os.stat(path).st_mtime)
days = (datetime.datetime.now() - file_modify).days
if (file_size > 50) and (days > 30):
print('壓縮包的路徑名稱是:{},大小為{:.2f}MB,建立檔案年份為:{}'.format(path,file_size,file_build_year))
批量操作檔案及檔案夾
建立檔案夾和多層檔案夾
import os
if not os.path.exists('新檔案夾名'):
os.mkdir('新檔案夾名')
# 建立多層檔案夾
os.makedirs('第一層檔案夾/第二層檔案夾/第三層檔案夾')
複制檔案或者檔案夾
複制、移動、删除檔案夾需要借助另一個子產品:shutil子產品
# 首先導入子產品
import shutil
import os
shutil.copy('檔案名', '目标檔案夾') # 将檔案複制到指定檔案夾
shutil.copy('檔案名', '目标檔案夾/新檔案名.txt') # 複制并重命名檔案
#如果複制的是檔案夾
shutil.copytree('源檔案夾','目标檔案夾')
# 如果不想複制檔案而是移動檔案,可以使用過move方法 使用方法類似copy,也可以移動檔案夾
shutil.move('檔案名', '目标檔案夾/')
shutil.move('源檔案夾','目标檔案夾/') # 檔案夾後面記住最後加斜杠/
# 若要删除檔案夾
shutil.rmtree('檔案夾名')
# 删除檔案
os.remove('檔案名')
案例3:
1. 鍵盤輸入一個路徑
2. 擷取裡面所有的mp4檔案
3. 重命名mp4檔案在每個檔案前面添加字首,字首就是檔案最後修改的年月日(如:2021-08-18_西遊記01.mp4)
4. 建立檔案夾:最新視訊
5. 将重命名的視訊批量移動到最新視訊檔案夾
import os
import datetime
import shutil
import glob
path = input('輸入要查詢的路徑:')
os.chdir(path)
if not os.path.exists('最新視訊'):
os.mkdir('最新視訊')
for dirpath,dirnames,files in os.walk('./'):
for file in os.scandir(dirpath):
if file.name.endswith(".mp4"):
tm = datetime.datetime.fromtimestamp(file.stat().st_mtime)
new_file = str(tm.year)+'-'+str(tm.month)+'-'+str(tm.day)+'-'+file.name
os.rename(dirpath + '/' + file.name,new_file)
file_ls = glob.glob('*.mp4')
for name in file_ls:
shutil.move(name,'最新視訊/')
print('over!!!')