天天看點

Python辦公自動化之OS子產品的常見用法

作者:千鋒IT教育

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))           

輸出結果:

Python辦公自動化之OS子產品的常見用法

或者使用:

for file in os.scandir():
     print(file.name, file.path, 
file.is_dir())           

可以調用file.stat()擷取更加詳細的檔案資訊。如:

Python辦公自動化之OS子產品的常見用法

其中:

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檔案:

Python辦公自動化之OS子產品的常見用法

此時使用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))           
Python辦公自動化之OS子產品的常見用法

批量操作檔案及檔案夾

建立檔案夾和多層檔案夾

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!!!')