使用python的os模組,簡單方便完成對資料夾、檔案及路徑的管理與訪問操作。
1 前言
在最近開發中,經常需要對檔案進行讀取、遍歷、修改等操作,想要快速、簡單的完成這些操作,我選擇用 python 。通過 python 的標準內建 os 模組,只需要幾行程式碼,即可完成想要的操作。經過對 os 的使用,本文把 os 模組的常用的操作進行總結,主要分為以下幾個劃分:
- 資料夾操作:即資料夾的建立、修改(改名/移動),查詢(檢視、遍歷)、刪除等。
- 檔案操作:即檔案的建立、修改、讀取、刪除等。
- (資料夾/檔案)路徑操作:即資料夾或檔案的路徑操作,如絕對路徑,檔名與路徑分割,副檔名分割等
本文涉及常用 的 os 函式的使用展示,主要使用 python 互動模式下進行程式碼說明。後續操作預設已經引入 os 模組,如下:
import os
2 資料夾操作
以本地 E://pythontest
目錄作為演示目錄,此目錄下當前檔案如下:
test
│ test.txt
└─test-1
test-1.txt
test
及 test-1
是資料夾,test.txt
及 test-1.txt
是檔案。
2.1 查詢操作
熟悉 linux 同學應該對 ls
/ pwd
/ cd
等操作不陌生,對應的 python 也有對應的方法,主要包括:
- listdir : 檔案及目錄列表
- getcwd :獲取當前目錄
- chdir :更換目錄
- stat :檔案及目錄基本資訊
- walk :遞迴遍歷目錄
>>> os.chdir("E://pythontest") # 更改目錄
>>> os.getcwd() # 獲取當前目錄
'E:\\pythontest'
>>> os.listdir("test") # 檔案及目錄列表,相對路徑
['test-1', 'test.txt']
>>> os.listdir("E://pythontest/test") # 檔案及目錄列表,絕對路徑
['test-1', 'test.txt']
>>> os.stat("test") # 獲取目錄資訊
os.stat_result(st_mode=16895, st_ino=4503599627377599, st_dev=266147611, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1590833033, st_mtime=1590832647, st_ctime=1590832207)
>>> os.stat("test/test.txt") # 獲取檔案資訊
os.stat_result(st_mode=33206, st_ino=2251799813692354, st_dev=266147611, st_nlink=1, st_uid=0, st_gid=0, st_size=4, st_atime=1590832653, st_mtime=1590832609, st_ctime=1590832598)
其中 stat 函式返回的是檔案或者目錄的基本資訊,具體如下:
- st_mode: inode 保護模式
- st_ino: inode 節點號。
- st_dev: inode 駐留的裝置。
- st_nlink: inode 的連結數。
- st_uid: 所有者的使用者ID。
- st_gid: 所有者的組ID。
- st_size: 普通檔案以位元組為單位的大小
- st_atime: 上次訪問的時間。
- st_mtime: 最後一次修改的時間。
- st_ctime: 建立時間。
日常使用中,我們一般使用 st_size 、st_ctime 及 st_mtime 獲取檔案大小,建立時間,修改時間。另外,我們看到輸出的時間是秒數,在這裡提一下,關於日期的轉換處理。
(1)秒數轉日期時間格式字串
>>> import time # 引入time模組
>>> timestruct = time.localtime(1590803070) # 轉換為時間結構體
>>> print(timestruct)
time.struct_time(tm_year=2020, tm_mon=5, tm_mday=30, tm_hour=9, tm_min=44, tm_sec=30, tm_wday=5, tm_yday=151, tm_isdst=0)
>>> time.strftime("%Y-%m-%d %H:%M:%S",timestruct) # 格式化時間
'2020-05-30 09:44:30'
(2)格式日期時間字串轉秒數
>>> import datetime # 引入datetime模組
>>> timeobject = datetime.datetime.strptime("2020-05-23 10:00:00","%Y-%m-%d %H:%M:%S") #解析時間字串為時間物件
>>> timeseconds=time.mktime(timeobject.timetuple()) # 獲取時間秒數
>>> print(int(timeseconds)) # 轉為int顯示
1590199200
-
遍歷操作
walk 函式對目錄進行遞迴遍歷,返回 root,dirs,files,分別對應當前的遍歷的目錄,此目錄中的子目錄及檔案。
>>> data = os.walk("test") # 遍歷test目錄
>>> for root,dirs,files in data: # 遞迴遍歷及輸出
... print("root:%s" % root)
... for dir in dirs:
... print(os.path.join(root,dir))
... for file in files:
... print(os.path.join(root,file))
...
root:test
test\test-1
test\test-2
test\test.txt
root:test\test-1
test\test-1\test-1.txt
root:test\test-2
test\test-2\test-2.txt
2.2 建立操作
-
mkdir :新建單個目錄,若目錄路徑中父目錄不存在,則建立失敗
-
makedirs :新建多個目錄,若目錄路徑中父目錄不存在,則自動建立
>>> os.mkdir("test")
>>> os.mkdir("test1/test1-1") # 父目錄不存在,報錯
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
FileNotFoundError: [WinError 3] 系統找不到指定的路徑。: 'test1/test1-1'
>>> os.makedirs("test1/test1-1") # 父目錄不存在,自動建立
>>> os.listdir("test1")
['test1-1']
2.3 刪除操作
- rmdir :刪除單個空目錄,目錄不為空則報錯
- removedirs : 按路徑刪除遞迴多級空目錄,目錄不為空則報錯
>>> os.rmdir("test1") # 若目錄不為空,報錯
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [WinError 145] 目錄不是空的。: 'test1'
>>> os.rmdir("test1/test1-1")
>>> os.removedirs("test1/test1-1") # 刪除多級空目錄
>>> os.listdir(".")
['test']
由於刪除空目錄的限制,更多的是使用 shutil
模組中的 rmtree
函式,可以刪除不為空的目錄及其檔案。
2.4 修改操作
- rename :重新命名目錄或檔案,可修改檔案或目錄的路徑(即移動操作),若目標檔案目錄不存在,則報錯。
- renames :重新命名目錄或檔案,若目標檔案目錄不存在,則自動建立
>>> os.makedirs("test1/test1-1")
>>> os.rename("test1/test1-1","test1/test1-2") # test1-1 修改為test1-2
>>> os.listdir("test1")
['test1-2']
>>> os.rename("test1/test1-2","test2/test2-2") # 由於test2目錄不存在,報錯
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
FileNotFoundError: [WinError 3] 系統找不到指定的路徑。: 'test1/test1-2' -> 'test2/test2-2'
>>> os.renames("test1/test1-2","test2/test2-2") # renames可自動建立不存在的目錄
>>> os.listdir("test2")
['test2-2']
如果目標路徑檔案已經存在,那麼os.rename()和os.renames()都會報錯:FileExistsError: [WinError 183] 當檔案已存在時,無法建立該檔案。
3 檔案操作
3.1 查詢操作
- open/read/close :檔案讀取
- stat :檔案資訊,詳細見前面資料夾中的 stat 說明
>>> f = os.open("test/test.txt", os.O_RDWR|os.O_CREAT) # 開啟檔案
>>> str_bytes = os.read(f,100) # 讀100位元組
>>> str = bytes.decode(str_bytes) # 位元組轉字串
>>> print(str)
test write data
>>> os.close(f) # 關閉檔案
注意 open/read/close 需要一起操作,其中 open 操作需要指定模式,上述是以讀寫模式開啟檔案,若檔案不存在則建立檔案。各模式具體如下:
flags -- 該引數可以是以下選項,多個使用 "|" 隔開:
- os.O_RDONLY: 以只讀的方式開啟
- os.O_WRONLY: 以只寫的方式開啟
- os.O_RDWR : 以讀寫的方式開啟
- os.O_NONBLOCK: 開啟時不阻塞
- os.O_APPEND: 以追加的方式開啟
- os.O_CREAT: 建立並開啟一個新檔案
- os.O_TRUNC: 開啟一個檔案並截斷它的長度為零(必須有寫許可權)
- os.O_EXCL: 如果指定的檔案存在,返回錯誤
- os.O_SHLOCK: 自動獲取共享鎖
- os.O_EXLOCK: 自動獲取獨立鎖
- os.O_DIRECT: 消除或減少快取效果
- os.O_FSYNC : 同步寫入
- os.O_NOFOLLOW: 不追蹤軟連結
3.2 建立操作
前面已提到,使用 open ,指定模式, 若檔案不存在,則建立。有點類似 linux 操作中的 touch。
>>> f = os.open("test/test.txt", os.O_RDWR|os.O_CREAT) # 若檔案不存在,則建立
>>> os.close(f)
3.3 修改操作
- open/write/close :寫入檔案內容
- rename ,renames : 與前面介紹的修改名稱、移動操作一致。
>>> f = os.open("test/test.txt", os.O_RDWR|os.O_CREAT) # 開啟檔案
>>> os.write(f,b"test write data") # 寫入內容
15
>>> os.close(f) # 關閉檔案
3.4 刪除
- remove :刪除檔案,注意不能刪除目錄(使用 rmdir/removedirs)
>>> os.remove("test/test-1") # 刪除目錄報錯
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
FileNotFoundError: [WinError 2] 系統找不到指定的檔案。: 'test/test1'
>>> os.remove("test/test.txt") # 刪除檔案
>>> os.listdir("test")
['test-1']
4 路徑操作
在使用檔案或目錄過程中,經常需要對檔案及目錄路徑進行處理,因此,os 中有一個子模組 path,專門就是處理路徑操作的。主要有以下操作:
- abspath :返回絕對路徑
>>> os.path.abspath("test")
'E:\\pythontest\\test'
- exists :判斷檔案或目錄是否存在
>>> os.path.exists("test")
True
>>> os.path.exists("test/test.txt")
False
>>> os.path.exists("test/test-1/test-1.txt")
True
- isfile/isdir :判斷是否為檔案/目錄
>>> os.path.isdir("test")
True
>>> os.path.isfile("test/test-1/test-1.txt")
True
- basename/dirname:獲取路徑尾部和路徑頭部。其實就是以路徑中最後一個
/
為分割符,分為頭(head) 和尾(tail)兩部分,tail 是 basename 返回的內容,head 是 dirname 返回的內容。經常用於獲取檔名,目錄名等操作
>>> os.path.basename("test/test-1/test-1.txt") # 檔名
'test-1.txt'
>>> os.path.basename("test/test-1/") # 空內容
''
>>> os.path.basename("test/test-1") # 目錄名
'test-1'
>>> os.path.dirname("test/test-1/test-1.txt") # 檔案所在目錄路徑
'test/test-1'
>>> os.path.dirname("test/test-1/") # 目錄路徑
'test/test-1'
>>> os.path.dirname("test/test-1") # 父目錄路徑
'test'
- join :合成路徑,即把兩個引數使用系統路徑分割符進行連線,形成完整路徑。
>>> os.path.join("test","test-1") # 連線兩個目錄
'test\\test-1'
>>> os.path.join("test\\test-1","test-1.txt") # 連線目錄與檔名
'test\\test-1\\test-1.txt'
- split :分割檔名和資料夾,即把 path 以最後一個斜線"/"為分隔符,切割為 head 和 tail ,以 (head, tail) 元組的形勢返回。
>>> os.path.split("test/test-1") # 分割目錄
('test', 'test-1')
>>> os.path.split("test/test-1/") # 以/結尾的目錄分割
('test/test-1', '')
>>> os.path.split("test/test-1/test-1.txt") # 分割檔案
('test/test-1', 'test-1.txt')
- splitext :分割路徑名和副檔名,把path 以最後一個副檔名分隔符“.”分割,切割為 head 和 tail ,以 (head, tail) 元組的形勢返回。注意與 split 的區別是分隔符的不同。
>>> os.path.splitext("test/test-1")
('test/test-1', '')
>>> os.path.splitext("test/test-1/")
('test/test-1/', '')
>>> os.path.splitext("test/test-1/test-1.txt") # 區分檔名及副檔名
('test/test-1/test-1', '.txt')
>>> os.path.splitext("test/test-1/test-1.txt.tmp") # 以最後的"."為分割點
('test/test-1/test-1.txt', '.tmp')
5 示例應用
下面以一些平時使用到的場景,對前面的操作函式進行綜合使用。
5.1 批量修改檔名
def batch_rename(dir_path):
itemlist = os.listdir(dir_path)
# 獲取目錄檔案列表
for item in itemlist:
# 連線成完整路徑
item_path = os.path.join(dir_path, item)
print(item_path)
# 修改檔名
if os.path.isfile(item_path):
splitext = os.path.splitext(item_path)
os.rename(item_path, splitext[0] + "-副本" + splitext[1])
5.2 遍歷目錄及子目錄下所有指定副檔名的檔案
def walk_ext_file(dir_path,ext):
# 遍歷
for root, dirs, files in os.walk(dir_path):
# 獲取檔名稱及路徑
for file in files:
file_path = os.path.join(root, file)
file_item = os.path.splitext(file_path)
# 輸出指定副檔名的檔案路徑
if ext == file_item[1]:
print(file_path)
5.3 按修改時間排序指定目錄下的檔案
def sort_file(dir_path):
# 排序前
itemlist = os.listdir(dir_path)
print(itemlist)
# 正向排序
itemlist.sort(key=lambda filename: os.path.getmtime(os.path.join(dir_path, filename)))
print(itemlist)
# 反向排序
itemlist.sort(key=lambda filename: os.path.getmtime(os.path.join(dir_path, filename)), reverse=True)
print(itemlist)
# 獲取最新修改的檔案
print(itemlist[0])
6 總結
在需要對檔案或者目錄進行操作時,python 是一個簡單快速選擇。本文通過 python 的標準內建 os 模組及子模組 os.path 的常用方法進行介紹,最後結合使用場景進行綜合使用。相信已經滿足大家對檔案及目錄操作的大部分需求。
參考資料
- python之os模組:
https://www.cnblogs.com/yufeihlf/p/6179547.html
- Python OS 檔案/目錄方法:
https://www.runoob.com/python/os-file-methods.html
- Python os.path() 模組:
https://www.runoob.com/python/python-os-path.html
往期文章
- MinIO 的分散式部署
- 利用MinIO輕鬆搭建靜態資源服務
- 搞定SpringBoot多資料來源(3):引數化變更源
- 搞定SpringBoot多資料來源(2):動態資料來源
- 搞定SpringBoot多資料來源(1):多套源策略
- java開發必學知識:動態代理
- 2019 讀過的好書推薦
我的公眾號(搜尋Mason技術記錄
),獲取更多技術記錄: