1 背景
有時候,我們想不起自己記錄的信息在哪個文件裏,需要一個個打開文件查找,非常麻煩。
這時候,我們可以藉助python,實現一鍵快速查找。
2 環境
Python 3.7.3 64-bit
tkinter
re
3 os.walk()
os.walk方法用於遍歷目錄和文件,簡單易用,可以幫助我們高效的處理目錄、文件方面的事情
os.walk方法語法格式如下:
os.walk(top=r"C:\Temp\TxGameDownload", topdown=True, onerror=None, followlinks=False)
- top:你要遍歷的目錄地址,如C:\Temp\TxGameDownload
- topdown:可選(默認爲True),爲True則優先遍歷top目錄,否則優先遍歷top的子目錄
- onerror:可選(默認爲None),Callable對象,需要異常時調用
- followlinks:可選(默認爲False),爲True則會遍歷目錄下的快捷方式實際所指向的目錄(注:windows下不生效,followlinks依賴於os.path.isdir和os.path.islink,很可惜,在windows下快捷方式返回的都是False)
- 返回結果:返回的是一個包含三元組dirpath, dirnames, filenames的Directory tree generator
簡單例子:
for root, dirs, files in os.walk(r"C:\Temp\TxGameDownload"):
for name in files:
print(os.path.join(root, name))
for name in dirs:
print(os.path.join(root, name))
4 快速查找主要代碼
def get_file_data(self, file_path):
"""獲取文件內容
:param file_path: 文件完整路徑
"""
data = None
try:
f = open(file_path, mode="r", encoding="utf-8") # 嘗試用utf8編碼打開
data = f.read().splitlines() # 將文件內容讀取爲按行分隔的列表
f.close() # 關閉文件
except UnicodeDecodeError:
f = open(file_path, mode="r", encoding="gb18030") # 嘗試用gb18030編碼打開
data = f.read().splitlines() # 將文件內容讀取爲按行分隔的列表
f.close() # 關閉文件
return data
def find_text(
self,
dir,
file_name_pattern="*",
file_content_pattern="",
stdout=print,
stderr=print,
output_max=613
):
"""查找文件內容
:param dir: 待查找目錄
:param file_name_pattern: 文件名模糊匹配
:param file_content_pattern: 待查找的文本內容
:param output_max: 字符串長度超過max值則不打印具體信息
"""
if file_content_pattern == "": stderr("請輸入查找內容!"); return # 查找內容不能爲空
if file_name_pattern == "": file_name_pattern = "*" # 文件名匹配爲空則查找目錄下所有文件
file_name_pattern = r"^{}$".format(file_name_pattern.replace("*", ".*")) # 轉換成正則表達式
file_content_pattern = r"{}".format(file_content_pattern.replace("*", ".*")) # 轉換成正則表達式
self.stop = False # 初始化強制停止標記
self.find_info = dict() # 初始化查找信息
for root, dirs, files in os.walk(dir): # 遍歷文件
if self.stop: # 用於控制手動強制停止查找
break
for file in files:
if self.stop: # 用於控制手動強制停止查找
break
file_path = os.path.abspath(os.path.join(root, file)) # 文件完整路徑
if re.search(file_name_pattern, file, re.I): # 判斷文件名是否滿足模糊匹配規則
try:
data = self.get_file_data(file_path=file_path) # 獲取文件數據
except UnicodeDecodeError:
stderr(file_path, str(e)) # 輸出異常信息(編碼問題)
continue
except PermissionError as e:
stderr(file_path, str(e)) # 輸出異常信息(權限問題)
continue
row_id = 0 # 行號
for line in data: # 遍歷每一行數據
row_id += 1 # 行號
if re.search(file_content_pattern, line, re.I): # 判斷是否爲要查找的內容
self.find_info[file_path] = self.find_info.get(file_path, 0) + 1 # 記錄查找到的信息
stdout( # 輸出查找到的信息
file_path,
"第" + str(row_id) + "行",
line if len(line) <= output_max else "……"
)
5 tkinter封裝
class ToplevelFileFindText(EToplevel):
"""一個頂級窗口(類似彈窗),用於一鍵查找文件內容
"""
FIND_START_DESC = "開始查找"
FIND_END_DESC = "結束查找"
def __init__(self, master=None, cnf={}, **kw):
super().__init__(master, cnf, **kw)
self.dir_to_find = None # 待查找目錄
self.button_ask_dir = self.create_button_ask_dir() # 創建按鈕(點擊後彈出文件夾選擇框)
self.button_ask_dir.grid(row=0, column=0, sticky=tk.NSEW)
self.dir = StringVar()
self.dir.set("")
self.label_dir = Label(self, textvariable=self.dir) # 創建標籤,用於顯示所選文件夾路徑
self.label_dir.grid(row=0, column=1, sticky=tk.W)
self.label_file_name_pattern = Label(self, text="文件名稱匹配") # 創建"文件名稱匹配"標籤
self.label_file_name_pattern.grid(row=1, column=0, sticky=tk.NSEW)
self.file_name_pattern = StringVar()
self.file_name_pattern.set("*.py")
self.entry_file_name_pattern = Entry(self, textvariable=self.file_name_pattern) # 創建"文件名稱匹配"輸入框
self.entry_file_name_pattern.grid(row=1, column=1, sticky=tk.NSEW)
self.label_file_content_pattern = Label(self, text="文件內容匹配") # 創建"文件內容匹配"標籤
self.label_file_content_pattern.grid(row=2, column=0, sticky=tk.NSEW)
self.file_content_pattern = StringVar()
self.file_content_pattern.set("import")
self.entry_file_content_pattern = Entry(self, textvariable=self.file_content_pattern) # 創建"文件內容匹配"輸入框
self.entry_file_content_pattern.grid(row=2, column=1, sticky=tk.NSEW)
self.button_find_start = self.create_button_find_start() # 創建一鍵查找按鈕
self.button_find_start.grid(row=3, column=0, sticky=tk.NSEW)
self.button_find_end = self.create_button_find_end() # 創建查找終止按鈕
self.button_find_end.grid(row=4, column=0, sticky=tk.NSEW)
self.file_tool = File() # 實例化文件查找工具
6 演示效果
7 完整代碼
github.com/TheUncleWhoGrowsBeans