因為工作原因,需要定期清理某個文件夾下面創建時間超過1年的所有文件,所以今天集中學習了一下Python對於本地文件及文件夾的操作。網上 這篇文章 簡明扼要地整理出最常見的os方法,抄襲如下:
- os.listdir(dirname):列出dirname下的目錄和文件
- os.getcwd():獲得當前工作目錄
- os.curdir:返回當前目錄('.')
- os.chdir(dirname):改變工作目錄到dirname
- os.path.isdir(name):判斷name是不是一個目錄,name不是目錄就返回false
- os.path.isfile(name):判斷name是不是一個文件,不存在name也返回false
- os.path.exists(name):判斷是否存在文件或目錄name
- os.path.getsize(name):獲得文件大小,如果name是目錄返回0L
- os.path.abspath(name):獲得絕對路徑
- os.path.normpath(path):規范path字符串形式
- os.path.split(name):分割文件名與目錄(事實上,如果你完全使用目錄,它也會將最后一個目錄作為文件名而分離,同時它不會判斷文件或目錄是否存在)
- os.path.splitext():分離文件名與擴展名
- os.path.join(path,name):連接目錄與文件名或目錄
- os.path.basename(path):返回文件名
- os.path.dirname(path):返回文件路徑
- os.remove(dir) #dir為要刪除的文件夾或者文件路徑
- os.rmdir(path) #path要刪除的目錄的路徑。需要說明的是,使用os.rmdir刪除的目錄必須為空目錄,否則函數出錯。
- os.path.getmtime(name) #獲取文件的修改時間
- os.stat(path).st_mtime#獲取文件的修改時間
- os.stat(path).st_ctime #獲取文件修改時間
- os.path.getctime(name)#獲取文件的創建時間
於是我照着這些方法,費半天勁,終於寫出了“清理某路徑下所有文件及文件夾”的方法,代碼如下:
1 import os 2 3 dirToBeEmptied = 'D:\_Data\Python\os' #需要清空的文件夾 4 5 ds = list(os.walk(dirToBeEmptied)) #獲得所有文件夾的信息列表 6 dsr = ds[::-1] #反轉該列表,從最底層的文件夾開始清算 7 8 for d in dsr: #遍歷該列表 9 print(d) #打印出列表項,觀察規律 10 if d[2] != []: #如果該路徑下有文件 11 for x in d[2]: #先將文件清理干凈 12 os.remove(os.path.join(d[0], x)) 13 for d in dsr: #再次遍歷該列表 14 if d[1] != []: #如果該路徑下有子文件夾 15 for y in d[1]: #將子文件夾清理干凈 16 os.rmdir(os.path.join(d[0], y))
之所以這么麻煩,是因為 os.rmdir() 有個毛病,只能刪除“空”文件夾。所以只能從最底層的文件夾開始清理,一級一級往上,才能清干凈。
后來想想,應該有更簡便的方法,因為清空文件夾是很常見的動作。查了Python官方文檔,發現了os以外的另一個模塊:shutil(高級文件操作),竟然有 shutil.rmtree() 的方法,不僅是清空,直接連文件夾都一起刪掉,太凶殘了!
為了“僅僅清空”,我搭配使用 shutil 模塊重寫了代碼:
1 import shutil, os 2 3 os.chdir('d:\_data\python\os') #進入要清空的目錄 4 ds = list(os.listdir()) #獲得該目錄下所有文件或文件夾列表 5 for d in ds: #遍歷該列表 6 if os.path.isfile(d): #如果列表項是文件 7 os.remove(d) #直接刪除 8 else: #如果不是文件,肯定是文件夾 9 shutil.rmtree(d) #也直接刪除
這下可就簡潔多了。
不過,清空一時爽,但已經偏離我原來的目的了:我只是想刪除過期的文件,但文件夾和所有子文件夾都得留着啊。倒也不難,最開始的代碼中,第1次遍歷列表就是只刪文件、不刪文件夾。只要再加個判斷語句,判斷出文件是否過期,就能達到目的了。
我要刪除的文件,實際上是做鏡像備份時,將已從主機刪除或更改的文件暫時保存下來,以備恢復之用。這些文件久了會越來越占空間,因此設定為1年過期。這些文件有一個特點,就是只會被復制過來一次,且不會有任何修改,因此只需要判斷其創建日期就可以。
想着是容易,但萬萬沒想到,Python對時間的處理這么復雜!涉及到兩個模塊:datetime 和 time。有時間必須重頭系統學習一下,但這里,我只關心現在需要的幾個方法:
- datetime.datetime.now() #獲取當前時間,返回值的格式類似 datetime.datetime(2017, 12, 14, 1, 29, 24, 406538)
- datetime.timedelta() #設定兩個時間之間的間隔,用於時間計算,可以設置的單位包括:(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0),默認都為0
- os.path.getctime() #獲取文件的創建時間,返回值的格式為一個巨大的浮點數,為1970年1月1日到這個創建時間所歷經的秒數
- datetime.datetime.fromtimestamp() #將os.path.getctime() 轉換為跟datetime.datetime.now()一樣的格式,以進行比較計算
弄清楚上面這些亂七八糟的之后,就可以寫代碼了:
1 import os, datetime 2 3 dirToBeEmptied = 'D:\_Data\Python\os' #需要清空的文件夾 4 5 ds = list(os.walk(dirToBeEmptied)) #獲得所有文件夾的信息列表 6 delta = datetime.timedelta(days=365) #設定365天前的文件為過期 7 now = datetime.datetime.now() #獲取當前時間 8 9 for d in ds: #遍歷該列表 10 os.chdir(d[0]) #進入本級路徑,防止找不到文件而報錯 11 if d[2] != []: #如果該路徑下有文件 12 for x in d[2]: #遍歷這些文件 13 ctime = datetime.datetime.fromtimestamp(os.path.getctime(x)) #獲取文件創建時間 14 if ctime < (now-delta): #若創建於delta天前 15 os.remove(x) #則刪掉
呼~~~~~~~~~
真夠復雜的!不知道有沒有簡便一點的辦法……