Contents ...
udn網路城邦
偉克多工作室-GPC改良版程式碼
2025/10/14 14:50
瀏覽35
迴響0
推薦0
引用0
import os


def find_folders_with_keyword(base_path, folder_keyword):

    """

    在指定路徑下搜尋包含關鍵字的資料夾

    

    參數:

    base_path (str): 要搜尋的基礎路徑

    folder_keyword (str): 資料夾名稱關鍵字

    

    返回:

    list: 符合條件的資料夾路徑清單

    """

    matching_folders = []

    

    try:

        # 列出基礎路徑下的所有項目

        items = os.listdir(base_path)

        

        # 將關鍵字轉為小寫,用於不區分大小寫的比較

        folder_keyword_lower = folder_keyword.lower()

        

        for item in items:

            item_path = os.path.join(base_path, item)

            

            # 檢查是否為資料夾,並且資料夾名稱包含關鍵字

            if os.path.isdir(item_path) and folder_keyword_lower in item.lower():

                matching_folders.append(item_path)

                

    except PermissionError:

        print(f"沒有權限存取路徑:{base_path}")

    except Exception as e:

        print(f"搜尋資料夾時發生錯誤:{e}")

    

    return matching_folders


def search_hierarchical_folders(base_path, folder_keywords):

    """

    按階層搜尋資料夾

    

    參數:

    base_path (str): 搜尋的基礎路徑

    folder_keywords (list): 資料夾關鍵字清單,按搜尋順序排列

    

    返回:

    list: 最終符合所有階層條件的資料夾路徑清單

    """

    current_paths = [base_path]

    

    for i, keyword in enumerate(folder_keywords):

        print(f"\n第 {i+1} 層搜尋:尋找包含 {keyword} 的資料夾")

        print("-" * 50)

        

        next_paths = []

        

        for current_path in current_paths:

            print(f"在路徑 {current_path} 中搜尋...")

            matching_folders = find_folders_with_keyword(current_path, keyword)

            

            if matching_folders:

                print(f"  找到 {len(matching_folders)} 個符合的資料夾:")

                for folder in matching_folders:

                    folder_name = os.path.basename(folder)

                    print(f"    - {folder_name} ({folder})")

                    next_paths.append(folder)

            else:

                print(f"  沒有找到包含 {keyword} 的資料夾")

        

        # 更新當前路徑清單

        current_paths = next_paths

        

        if not current_paths:

            print(f"\n搜尋中斷:在第 {i+1} 層沒有找到任何符合條件的資料夾")

            return []

    

    return current_paths


def search_code_files_in_folder(folder_path, content_keyword):

    """

    在指定資料夾中搜尋包含關鍵字的程式碼檔案內容

    

    參數:

    folder_path (str): 要搜尋的資料夾路徑

    content_keyword (str): 要搜尋的內容關鍵字

    

    返回:

    bool: 是否找到任何符合條件的檔案

    """

    print(f"\n--- 搜尋資料夾:{folder_path} ---")

    

    # 支援的檔案類型

    supported_extensions = [.txt, .py, .ino, .c, .cpp, .h, .hpp]

    

    try:

        # 列出資料夾中的所有檔案

        all_files = os.listdir(folder_path)

        code_files = []

        

        for file in all_files:

            file_path = os.path.join(folder_path, file)

            if os.path.isfile(file_path):

                # 檢查副檔名是否在支援清單中

                _, ext = os.path.splitext(file)

                if ext.lower() in supported_extensions:

                    code_files.append(file)

    

    except PermissionError:

        print(f"沒有權限存取資料夾:{folder_path}")

        return False

    except Exception as e:

        print(f"讀取資料夾時發生錯誤:{e}")

        return False

    

    # 如果沒有找到程式碼檔案

    if not code_files:

        print(f"此資料夾中沒有找到程式碼檔案 (支援類型: {, .join(supported_extensions)})")

        return False

    

    print(f"找到 {len(code_files)} 個程式碼檔案")

    

    # 將關鍵字轉為小寫,用於不區分大小寫的搜尋

    content_keyword_lower = content_keyword.lower()

    found = False

    

    # 逐一檢查每個檔案

    for code_file in code_files:

        file_path = os.path.join(folder_path, code_file)

        try:

            # 以 UTF-8 編碼讀取檔案內容

            with open(file_path, r, encoding=utf-8) as f:

                content = f.read()

            

            # 檢查檔案內容是否包含關鍵字

            if content_keyword_lower in content.lower():

                found = True

                print(f"\n★ 找到關鍵字:{content_keyword} 於檔案:{file_path}")

                print("-" * 80)

                print(f"檔案完整內容:")

                print("-" * 80)

                print(content)

                print("-" * 80)

                print(f"檔案結束\n")

                

        except UnicodeDecodeError:

            # 如果 UTF-8 解碼失敗,嘗試其他編碼

            try:

                # 嘗試 Big5 編碼

                with open(file_path, r, encoding=big5) as f:

                    content = f.read()

                if content_keyword_lower in content.lower():

                    found = True

                    print(f"\n★ 找到關鍵字:{content_keyword} 於檔案:{file_path}")

                    print("-" * 80)

                    print(f"檔案完整內容:")

                    print("-" * 80)

                    print(content)

                    print("-" * 80)

                    print(f"檔案結束\n")

            except:

                # 嘗試 latin-1 編碼

                try:

                    with open(file_path, r, encoding=latin-1) as f:

                        content = f.read()

                    if content_keyword_lower in content.lower():

                        found = True

                        print(f"\n★ 找到關鍵字:{content_keyword} 於檔案:{file_path}")

                        print("-" * 80)

                        print(f"檔案完整內容:")

                        print("-" * 80)

                        print(content)

                        print("-" * 80)

                        print(f"檔案結束\n")

                except Exception as e:

                    print(f"讀取檔案 {code_file} 時發生編碼錯誤:{e}")

        except Exception as e:

            print(f"讀取檔案 {code_file} 時發生錯誤:{e}")

    

    return found


def search_specific_filetypes(base_path, keyword):

    """

    搜尋包含關鍵字的資料夾並列出特定類型檔案

    

    參數:

    base_path (str): 搜尋的基礎路徑

    keyword (str): 要搜尋的關鍵字(用於資料夾或檔案名稱)

    

    返回:

    bool: 是否找到任何符合條件的資料夾或檔案

    """

    print(f"\n{=*80}")

    print(f"搜尋包含 {keyword} 的資料夾或檔案")

    print(f"基礎路徑:{base_path}")

    print(f"{=*80}")

    

    # 定義要搜尋的檔案類型

    file_types = [.pdf, .doc, .docx, .ppt, .pptx, .txt]

    type_names = {

        .pdf: PDF檔案,

        .doc: WORD檔案,

        .docx: WORD檔案,

        .ppt: PPT檔案,

        .pptx: PPT檔案,

        .txt: 文字檔案

    }

    

    # 將關鍵字轉為小寫,用於不區分大小寫的搜尋

    keyword_lower = keyword.lower()

    found = False

    

    # 使用集合追蹤已顯示的檔案路徑

    printed_files = set()

    

    try:

        # 搜尋所有子目錄

        for root, dirs, files in os.walk(base_path):

            # 檢查當前目錄名稱是否包含關鍵字

            folder_name = os.path.basename(root)

            if keyword_lower in folder_name.lower():

                print(f"\n★ 找到包含關鍵字的資料夾:{root}")

                found = True

                

                # 列出此資料夾中的特定檔案類型

                for file in files:

                    file_path = os.path.join(root, file)

                    if os.path.isfile(file_path):

                        _, ext = os.path.splitext(file)

                        ext_lower = ext.lower()

                        if ext_lower in file_types:

                            # 只顯示尚未顯示過的檔案

                            if file_path not in printed_files:

                                print(f"  - {type_names.get(ext_lower, ext.upper())}: {file_path}")

                                printed_files.add(file_path)

            

            # 檢查檔案名稱是否包含關鍵字

            for file in files:

                file_path = os.path.join(root, file)

                if os.path.isfile(file_path):

                    _, ext = os.path.splitext(file)

                    ext_lower = ext.lower()

                    

                    # 如果檔案類型符合且檔案名稱包含關鍵字

                    if ext_lower in file_types and keyword_lower in file.lower():

                        # 只顯示尚未顯示過的檔案

                        if file_path not in printed_files:

                            if not found:  # 如果還沒找到任何項目,先顯示標題

                                print(f"\n★ 找到包含關鍵字的檔案:")

                                found = True

                            print(f"  - {type_names.get(ext_lower, ext.upper())}: {file_path}")

                            printed_files.add(file_path)

    

    except PermissionError as e:

        print(f"沒有權限存取路徑:{e}")

    except Exception as e:

        print(f"搜尋檔案時發生錯誤:{e}")

    

    return found


def get_folder_keywords():

    """

    取得使用者輸入的階層資料夾關鍵字

    

    返回:

    list: 資料夾關鍵字清單,如果使用者取消則返回 None

    """

    folder_keywords = []

    

    print("\n請依序輸入要搜尋的資料夾關鍵字(按階層順序)")

    print("範例:第一層輸入 hello,第二層輸入 world")

    print("輸入 off 結束輸入,輸入 q 返回主選單")

    

    layer = 1

    while True:

        keyword = input(f"第 {layer} 層資料夾關鍵字:").strip()

        

        if keyword.lower() == q:

            return None

        elif keyword.lower() == off:

            if not folder_keywords:

                print("至少需要輸入一個資料夾關鍵字!")

                continue

            else:

                break

        elif keyword == :

            print("請輸入關鍵字,或輸入 off 結束輸入")

            continue

        else:

            folder_keywords.append(keyword)

            layer += 1

    

    return folder_keywords


def hierarchical_search(base_path, folder_keywords, content_keyword):

    """

    執行階層式搜尋

    

    參數:

    base_path (str): 搜尋的基礎路徑

    folder_keywords (list): 資料夾關鍵字清單

    content_keyword (str): 檔案內容關鍵字

    """

    print(f"\n{=*80}")

    print(f"階層式資料夾搜尋")

    print(f"基礎路徑:{base_path}")

    print(f"搜尋階層:{ -> .join(folder_keywords)}")

    print(f"內容關鍵字:{content_keyword}")

    print(f"{=*80}")

    

    # 階層搜尋資料夾

    final_folders = search_hierarchical_folders(base_path, folder_keywords)

    

    if not final_folders:

        print(f"\n沒有找到符合所有階層條件的資料夾")

        return

    

    print(f"\n{=*80}")

    print(f"階層搜尋完成!找到 {len(final_folders)} 個最終資料夾:")

    for folder in final_folders:

        print(f"  - {folder}")

    

    print(f"\n{=*80}")

    print(f"開始在最終資料夾中搜尋包含 {content_keyword} 的程式碼檔案")

    print(f"{=*80}")

    

    overall_found = False

    

    # 在每個最終資料夾中搜尋程式碼檔案內容

    for folder_path in final_folders:

        found_in_folder = search_code_files_in_folder(folder_path, content_keyword)

        if found_in_folder:

            overall_found = True

    

    if not overall_found:

        print(f"\n在所有最終資料夾中都沒有找到包含 {content_keyword} 的程式碼檔案")


def get_base_path():

    """

    取得使用者輸入的基礎搜尋路徑

    

    返回:

    str: 有效的資料夾路徑,如果使用者取消則返回 None

    """

    while True:

        base_path = input("請輸入要搜尋的基礎路徑(輸入 q 返回主選單):").strip()

        

        # 如果使用者想要返回

        if base_path.lower() == q:

            return None

        

        # 檢查輸入是否為空

        if not base_path:

            print("請輸入有效的路徑!")

            continue

        

        # 如果輸入的是相對路徑,提供建議

        if base_path == .:

            base_path = os.getcwd()

            print(f"將搜尋目前工作目錄:{base_path}")

        

        # 檢查路徑是否存在

        if os.path.exists(base_path) and os.path.isdir(base_path):

            return base_path

        else:

            print(f"路徑 {base_path} 不存在或不是有效的資料夾路徑,請重新輸入。")

            print("提示:可以輸入 . 來搜尋目前工作目錄")


# 主程式

if __name__ == "__main__":

    print("階層式 程式碼檔案搜尋程式")

    print("=" * 80)

    print("此程式會:")

    print("1. 按照您指定的階層順序搜尋資料夾")

    print("   例如:路徑 -> hello資料夾 -> world資料夾")

    print("2. 在最終找到的資料夾中搜尋包含關鍵字的程式碼檔案內容")

    print("3. 支援的檔案類型:.txt, .py, .ino, .c, .cpp, .h, .hpp")

    print("4. 支援不區分大小寫的搜尋")

    print("5. 當找到關鍵字時,會完整顯示檔案內容")

    print("6. 支援多層資料夾階層搜尋")

    print("7. 輸入 off 結束資料夾關鍵字輸入")

    print("=" * 80)

    

    while True:

        print("\n主選單:")

        print("1. 開始階層搜尋")

        print("2. 離開程式")

        print("3. 搜尋特定檔案類型的檔案(PDF/WORD/PPT/TXT)")

        

        choice = input("請選擇功能(1, 2 或 3):").strip()

        

        if choice == 2:

            print("感謝使用!")

            break

        elif choice == 1:

            # 取得基礎搜尋路徑

            base_path = get_base_path()

            if base_path is None:

                continue  # 使用者選擇返回主選單

            

            # 開始搜尋的迴圈

            while True:

                print(f"\n目前搜尋路徑:{base_path}")

                print("輸入 q 返回主選單,輸入 p 更換搜尋路徑")

                

                # 取得階層資料夾關鍵字

                folder_keywords = get_folder_keywords()

                

                if folder_keywords is None:

                    break  # 使用者選擇返回主選單

                

                # 顯示搜尋階層

                print(f"\n您設定的搜尋階層:{ -> .join(folder_keywords)}")

                confirm = input("確認開始搜尋?(y/n/q):").strip().lower()

                

                if confirm == q:

                    break

                elif confirm == p:

                    new_path = get_base_path()

                    if new_path:

                        base_path = new_path

                    continue

                elif confirm != y:

                    continue

                

                # 取得內容關鍵字

                content_keyword = input("請輸入要搜尋的檔案內容關鍵字:").strip()

                

                if content_keyword.lower() == q:

                    break

                elif not content_keyword:

                    print("請輸入有效的內容關鍵字!")

                    continue

                

                # 執行階層搜尋

                hierarchical_search(base_path, folder_keywords, content_keyword)

                

                print("\n" + "="*80)

        

        # 模式3:搜尋特定檔案類型的檔案(PDF/WORD/PPT/TXT)

        elif choice == 3:

            # 取得基礎搜尋路徑

            base_path = get_base_path()

            if base_path is None:

                continue  # 使用者選擇返回主選單

            

            while True:

                print(f"\n目前搜尋路徑:{base_path}")

                print("輸入 q 返回主選單,輸入 p 更換搜尋路徑")

                

                # 取得關鍵字

                keyword = input("請輸入要搜尋的關鍵字(資料夾或檔案名稱):").strip()

                

                if keyword.lower() == q:

                    break

                elif keyword.lower() == p:

                    new_path = get_base_path()

                    if new_path:

                        base_path = new_path

                    continue

                elif not keyword:

                    print("請輸入有效的關鍵字!")

                    continue

                

                # 執行搜尋

                found = search_specific_filetypes(base_path, keyword)

                

                if not found:

                    print(f"\n沒有找到包含 {keyword} 的資料夾或檔案")

                

                print("\n" + "="*80)

                

        else:

            print("請輸入 1, 2 或 3!")
你可能會有興趣的文章:

限會員,要發表迴響,請先登入