pathlib函式庫:操作文字檔案與資料夾的好幫手-3
是否曾有過這樣的經驗?明明知道檔案在電腦裡,但卻不記得它的完整名稱,只有片段的印象、只記得檔案的部分名稱。或者,工作上需要批次建立大量資料夾,例如依照一份名單上的名字,分別建立每個人的資料夾,但每次都得一個一個的建立。面對如此繁瑣的步驟,是不是覺得有點頭疼?這時候,可能就會想:「該不會有工具可以幫助我們解決這些問題吧?」
沒錯,Python就是您的得力助手。在這篇文章中,我們將探討如何透過Python的pathlib
函式庫,輕鬆找回那些「不知道名稱,只有印象」的檔案,以及自動化地完成批次建立資料夾的任務,讓原本繁瑣的步驟變得輕鬆簡單。
讓我們一起來探索,如何利用Python的pathlib
函式庫,讓檔案和資料夾的操作變得更加輕鬆。
搜尋檔案名稱
我們都有過這樣的經驗,知道檔案在某個地方,但只記得它名稱的一部分。這時,想像一下,如果只要提供這些斷簡殘篇,電腦就能馬上在指定資料夾裡找出所有符合的檔案名稱,那是不是感覺超級方便?透過pathlib
函式庫可以做到這點,接下來,讓我們開始說明該如何做到。
A. 套件與命令方法
首先,依舊會使用到Path套件,它是這次任務的核心,協助我們處理路徑和檔案相關的操作。再來,是rglob()
命令,可以幫我們搜尋指定資料夾及其子資料夾中的所有檔案。另外,有時候我們只想知道某些特定的名稱或片段是否出現在檔案中,這時count()
命令就派上用場,它可以助我們計算特定字串在文本中出現的次數。
總之,這些工具和命令組合起來,能使搜尋過程更為簡單和高效。下表整理了即將使用的套件和命令:
B. 概念
想要找回那個「似曾相識」的檔案名稱時,該如何下手呢?其實,答案就在資料夾的檔案名稱裡。
要達到這樣子的功能,必須讓電腦取得特定資料夾與子資料夾的所有檔案名稱。首先,得讓電腦拜訪特定的資料夾及其子資料夾,取得每一個角落裡的檔案名稱。接著,就是比對了。電腦會根據使用者提供的部分名稱訊息,進行逐一比對。當它發現有檔案名稱中包含了先前提供的字串時,它就會告訴我們完整的檔案名稱和位置。
# count的用法
您可能會好奇,這樣的比對機制是怎麼運作的?其實,在這裡使用了一個叫做 count
的方法。這是一個很好用的工具,尤其當您想要知道某個字串出現了多少次的時候。例如,當我們用 'abcmarket.txt'.count('abc')
,它就會告訴我們 abc
出現了一次。反之,如果沒有找到,就會顯示0次。
讓我們再看一下範例:
text = 'abcmarket.txt'
word1 = 'abc'
word2 = 'mak'
count1 = text.count(word1)
print(f'找到word1:{count1}個')
count2 = text.count(word2)
print(f'找到word2:{count2}個')
透過上述的程式碼,可以清楚看到,當檔案名稱 text
中出現了我們想要找的 word1
或 word2
,count
就會給我們肯定的答案。
C. 實作
經過前面的概念說明,是否已經讓您躍躍欲試,希望親手實作看看呢?現在就一起來一探究竟。我們要利用以前學到的rglob()
,與今天介紹的count()
命令,來撰寫搜尋檔名的程式。
1.匯入套件
在此依舊要匯入pathlib
套件。由於我們要使用pathlib
套件中的Path
類別,於是透過下面方式匯入:
# 匯入
from pathlib import Path
2.參數
接下來設定參數。這裡設定了兩個參數:folder
是我們要搜尋的資料夾名稱,而 search_value
則是要搜尋的字串。
# 設定參數
folder = 'doc'
search_value = "test"
3.函式
接下來是主角,findfilename
函式。這個函式的作用是,根據提供的資料夾和部分檔名,幫我們找出所有符合條件的檔案名稱。
# 函式
def findfilename(folder,findword):
cnt = 0
msg = ''
filelist =[]
for p in Path(folder).rglob("*.*"):
if p.name[0] != ".":
filelist.append(str(p))
for filename in filelist:
if filename.count(findword) > 0:
msg += filename + "\\n"
cnt += 1
msg = "符合條件的檔案個數 = " + str(cnt) + "\\n" + msg
return msg
首先,透過 rglob("*.*")
取得所有檔案名稱,並存入 filelist
。請注意,這裡我們放了一個判斷式: if p.name[0] != "."
這是為了過濾掉系統生成的隱藏檔案。
接著,只需透過簡單的 count()
方法,檢查每個檔案名稱是否包含我們提供的部分檔名 findword
。
最後,函式將返回所有符合條件的檔案名稱,以及這些檔案的總數。
4.執行函式
最後一步,就是執行函式並列印出結果:
# 執行函式
msg = findfilename(folder,search_value)
print(msg)
這樣,只要簡單的幾行程式,就可以輕鬆找出所有想要的檔案名稱。
5.優化程式
接下來,可以針對上面的程式碼進行優化。以下是程式碼優化的方式:
- 參數不在固定,改由透過使用者自行輸入。
- 移除了中間的
filelist
。可以只在一次迴圈內完成所有操作,無需先存儲所有的檔案名稱。 - 直接使用
Path
對象進行操作,避免不必要的str
轉換。 - 用
+=
進行增加,讓程式碼更簡潔。
from pathlib import Path
# 輸入參數
folder =input('請輸入資料夾名稱')
search_value = input('請輸入關鍵字')
# 函式
def findfilename(folder, findword):
count = 0
msg = ''
for p in Path(folder).rglob("*.*"):
if p.name[0] != "." and findword in p.name:
msg += str(p) + "\\n"
count += 1
msg = f"符合條件的檔案個數 = {count}\\n{msg}"
return msg
# 執行函式
msg = findfilename(folder, search_value)
print(msg)
此外,我們也可以將程式碼以物件導向程式設計 (OOP) 的方式表現。這樣能夠使程式更加模組化和具備可擴充性。
from pathlib import Path
class FileFinder:
def __init__(self, folder: str, search_value: str):
self.folder = folder
self.search_value = search_value
self.matched_files = []
def search_files(self):
for p in Path(self.folder).rglob("*.*"):
if p.name[0] != "." and self.search_value in p.name:
self.matched_files.append(p)
def display_results(self):
count = len(self.matched_files)
msg = '\\n'.join([str(p) for p in self.matched_files])
print(f"符合條件的檔案個數 = {count}\\n{msg}")
def run(self):
self.search_files()
self.display_results()
# 設定參數
folder =input('請輸入資料夾名稱')
search_value = input('請輸入關鍵字')
finder = FileFinder(folder, search_value)
finder.run()
利用csv檔案,批次建立資料夾
在現今的企業環境中,效率是每位員工追求的目標。想像一下,若公司要舉辦大型的教育訓練,涉及的員工多達100位。如果要手動為每位員工建立專屬的資料夾,不僅耗時,也容易出錯。那麼,是否有更聰明的方法,讓我們充分利用電腦的力量,輕鬆完成這樣看似繁瑣的任務呢?
在本段落中,將會探討如何透過Python,結合csv檔案,輕鬆完成這項任務,讓例行公事不再是負擔。
A. 套件與命令方法
在Python中,當我們要處理csv格式的檔案時,就會想到csv套件。由於它是標準函式庫的一部分,只需要簡單的import
語法,就能將它引入程式中。
而對於檔案的開啟,通常會使用open
命令,這可以讓我們輕鬆地讀取或寫入檔案。
B. 概念
假設手上有一份詳細的員工名冊時,並且它是簡單而且結構清楚的CSV檔。當電腦拿到這份CSV檔案後,會先開啟這份檔案,逐行讀取裡面的內容。每讀取到一位員工的名稱,它就會立刻在指定位置建立一個對應的資料夾。透過這樣的方式,電腦能夠迅速且精確地為每位員工建立屬於他們自己的專屬資料夾,確保資料的整齊與管理的便利性。
#open用法
當我們使用Path
套件操作檔案時,可以使用open命令開啟它:
f = Path(檔案路徑名稱).open(encoding="UTF-8")
如上面的語法,當使用open開啟檔案時,並在其中放入 encoding="UTF-8"
的參數,這樣子就會載入UTF-8編碼的CSV檔案。
#取得CSV檔案的各個元素
在讀取了csv檔案之後,可以透過下面的方式取得它的每一個元素:
import csv
data = csv.reader(f)
for row in data:
for value in row:
print(value)
結合上述兩個概念,可以透過下面這方式讀取csv檔案中的所有資料:
infile = "doc/namelist.csv"
f = Path(infile).open(encoding="UTF-8")
data = csv.reader(f)
for row in data:
for value in row:
print(value)
為了使程式更加周延,我們可以使用try
和except
來處理可能出現的錯誤:
try:
可能發生錯誤的處理
except:
發生錯誤時的處理
上面的程式修改之後,就會像下面這一段:
infile = "doc/namelist.csv"
try:
f = Path(infile).open(encoding="UTF-8")
data = csv.reader(f)
for row in data:
for value in row:
print(value)
except:
print("檔案不存在,無法讀取檔案")
使用此方法,可以讓程式在出現錯誤時,給出有用的提示,而不是直接當掉。
C. 實作
1.匯入套件
首先,我們匯入必要的套件pathlib
中的Path
與csv
:
# 匯入
from pathlib import Path
import csv
2.參數
並且設定一些基礎參數:
# 參數
infile = "doc/namelist.csv"
value1 = "doc/outputfolder"
3.函式
在這裡,建立了一個函式makefolders
,它可以從csv檔案中讀取資料,並在指定的資料夾中建立新的資料夾:
# 函式
def makefolders(readfile,savefolder):
try:
msg = ''
Path(savefolder).mkdir(exist_ok=True)
f = Path(infile).open(encoding="UTF-8")
csvdata = csv.reader(f)
for row in csvdata:
for foldername in row:
newfolder = Path(savefolder).joinpath(foldername)
newfolder.mkdir(exist_ok=True)
msg += "在" + savefolder + "建立了" + foldername + "了。\\n"
return msg
except:
return readfile + " :無法載入檔案。"
4.執行函式
直接呼叫上述的函式,開始建立資料夾。
# 執行函式
msg = makefolders(infile,value1)
print(msg)
5.優化程式
我們可以透過以下方式優化程式碼:
- 使用
with
語句自動關閉檔案,用以避免檔案處於開啟狀態太久。 - 移除
msg
字串的連續拼接,改用 list comprehension 來進行格式化。 - 優化錯誤處理程序,捕捉具體的異常,使錯誤訊息更具意義。
- 避免使用全域變數
infile
,直接使用函式參數readfile
。
下面是依照上面原則優化後的程式碼:
from pathlib import Path
import csv
def makefolders(readfile, savefolder):
msgs = []
Path(savefolder).mkdir(exist_ok=True)
try:
with Path(readfile).open(encoding="UTF-8") as f:
csvdata = csv.reader(f)
for row in csvdata:
for foldername in row:
newfolder = Path(savefolder).joinpath(foldername)
newfolder.mkdir(exist_ok=True)
msgs.append(f"在{savefolder}建立{foldername}了。")
except FileNotFoundError:
return f"{readfile} :無法載入檔案。"
except Exception as e:
return str(e)
return '\\\\n'.join(msgs)
# 參數
infile = "doc/namelist.csv"
value1 = "doc/outputfolder"
# 執行函式
msg = makefolders(infile, value1)
print(msg)
經過這些修改,使得程式碼更為簡潔、更具有可讀性,並且更能確實地處理潛在的錯誤。
或者也可以使用物件導向程式設計 (OOP)的方式優化程式碼。以下是使用物件導向程式設計方式重構後的程式碼:
- 建立了一個
FolderManager
類別來處理所有與文件和資料夾相關的操作。 __init__
方法中,初始化必要的參數。makefolders
方法現在成為類別的一個方法,而不再是獨立的函式。
from pathlib import Path
import csv
class FolderManager:
def __init__(self, readfile, savefolder):
self.readfile = readfile
self.savefolder = savefolder
def makefolders(self):
msgs = []
Path(self.savefolder).mkdir(exist_ok=True)
try:
with Path(self.readfile).open(encoding="UTF-8") as f:
csvdata = csv.reader(f)
for row in csvdata:
for foldername in row:
newfolder = Path(self.savefolder).joinpath(foldername)
newfolder.mkdir(exist_ok=True)
msgs.append(f"在{self.savefolder}建立{foldername}了。")
except FileNotFoundError:
return f"{self.readfile} :無法載入檔案。"
except Exception as e:
return str(e)
return '\\\\n'.join(msgs)
# 參數
infile = "doc/namelist.csv"
value1 = "doc/outputfolder"
# 初始化物件並執行方法
folder_mgr = FolderManager(infile, value1)
msg = folder_mgr.makefolders()
print(msg)
這種物件導向程式設計的方式使得程式碼結構更為清晰,如將來需要增加更多的方法或屬性。目前這種寫法也提供了更多的擴充性,
結語
隨著時間的推進,我們一同探索了Python的pathlib
函式庫,並深化了對它的認識。從一開始的迷茫和不確定,到如今能夠輕易地操作檔案和資料夾,每一次的嘗試都是成長的軌跡。
回顧過去的我們,在面對眾多的檔案和資料夾時,可能感到手足無措。但現在,只需幾行程式碼,就能將繁瑣的工作迎刃而解。這樣的便利不只節省了時間,更讓工作流程變得更為精準、更加高效。
期望這篇文章為您開啟一扇新的大門,引領進一步探索Python的知識寶藏。憑藉著Python這得力的夥伴,未來的旅程雖長,我們的道路卻將更加光明。