【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

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