【tkGo】一鍵查找文件內容

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章