質問するログイン新規登録
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

312閲覧

PythonにてWin インデックス検索で結果からエクスプローラーを開きたい

kinpati

総合スコア1

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2025/08/22 19:32

0

0

実現したいこと

  • 検索結果に出た親フォルダをダブルクリックしてエクスプローラーを開きたい

前提

PythonにてWin インデックス検索のシステムを作っています。
検索結果に出た親フォルダをダブルクリックしてエクスプローラーを開きたいのですがどうしても出来ません。

発生している問題・エラーメッセージ

検索結果の親フォルダをダブルクリックすると「フォルダが存在しません」とのメッセージが出ます。

該当のソースコード

Python

1import os 2import threading 3import tkinter as tk 4from tkinter import ttk, messagebox, filedialog 5import pythoncom 6import win32com.client 7from urllib.parse import urlparse, unquote 8from pathlib import Path 9import subprocess 10 11class WinIndexSearchApp: 12 def __init__(self, root): 13 self.root = root 14 self.root.title("Windowsインデックス検索ツール(親フォルダを開く対応)") 15 self.root.geometry("1000x600") 16 17 self.cancel_flag = False 18 19 frame_top = tk.Frame(root) 20 frame_top.pack(fill=tk.X, padx=10, pady=5) 21 22 tk.Label(frame_top, text="検索フォルダ(省略可):").pack(side=tk.LEFT) 23 self.folder_var = tk.StringVar() 24 tk.Entry(frame_top, textvariable=self.folder_var, width=50).pack(side=tk.LEFT, padx=5) 25 tk.Button(frame_top, text="参照", command=self.browse_folder).pack(side=tk.LEFT, padx=5) 26 27 tk.Label(frame_top, text="キーワード:").pack(side=tk.LEFT, padx=(10,5)) 28 self.keyword_entry = tk.Entry(frame_top, width=30) 29 self.keyword_entry.pack(side=tk.LEFT, padx=5) 30 self.keyword_entry.bind("<Return>", self.start_search_event) 31 tk.Button(frame_top, text="検索", command=self.search_thread).pack(side=tk.LEFT, padx=5) 32 tk.Button(frame_top, text="キャンセル", command=self.cancel_search).pack(side=tk.LEFT, padx=5) 33 34 self.progress_var = tk.DoubleVar() 35 self.progress_bar = ttk.Progressbar(root, variable=self.progress_var, maximum=100) 36 self.progress_bar.pack(fill=tk.X, padx=10, pady=5) 37 38 frame_table = tk.Frame(root) 39 frame_table.pack(fill=tk.BOTH, expand=True, padx=10, pady=5) 40 41 columns = ("#", "FileName", "Folder") 42 self.tree = ttk.Treeview(frame_table, columns=columns, show="headings") 43 self.tree.heading("#", text="#") 44 self.tree.heading("FileName", text="ファイル名") 45 self.tree.heading("Folder", text="親フォルダ") 46 self.tree.column("#", width=50, anchor="center") 47 self.tree.column("FileName", width=300, anchor="w") 48 self.tree.column("Folder", width=600, anchor="w") 49 50 vsb = ttk.Scrollbar(frame_table, orient="vertical", command=self.tree.yview) 51 self.tree.configure(yscroll=vsb.set) 52 self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) 53 vsb.pack(side=tk.RIGHT, fill=tk.Y) 54 55 self.tree.bind("<Double-1>", self.open_folder) 56 57 def browse_folder(self): 58 folder = filedialog.askdirectory() 59 if folder: 60 self.folder_var.set(folder) 61 62 def start_search_event(self, event): 63 self.search_thread() 64 65 def cancel_search(self): 66 self.cancel_flag = True 67 68 def search_thread(self): 69 threading.Thread(target=self.search, daemon=True).start() 70 71 @staticmethod 72 def get_parent_folder(raw_path): 73 if not raw_path: 74 return None 75 parsed = urlparse(raw_path) 76 if parsed.scheme == 'file': 77 path = unquote(parsed.path) 78 if path.startswith('/') and path[2] == ':': 79 path = path[1:] 80 else: 81 path = raw_path 82 path = os.path.abspath(path) 83 return os.path.dirname(path) 84 85 def search(self): 86 self.cancel_flag = False 87 keyword = self.keyword_entry.get().strip() 88 if not keyword: 89 messagebox.showerror("エラー", "検索キーワードを入力してください") 90 return 91 92 folder_scope = self.folder_var.get().strip() or "C:\\" 93 folder_scope = os.path.abspath(folder_scope) 94 95 pythoncom.CoInitialize() 96 try: 97 conn = win32com.client.Dispatch("ADODB.Connection") 98 conn.Open("Provider=Search.CollatorDSO;Extended Properties='Application=Windows';") 99 cmd = win32com.client.Dispatch("ADODB.Command") 100 cmd.ActiveConnection = conn 101 cmd.CommandText = f""" 102 SELECT System.ItemPathDisplay, System.FileName 103 FROM SYSTEMINDEX 104 WHERE scope='file:{folder_scope}' 105 AND System.FileName LIKE '%{keyword}%' 106 """ 107 rs = cmd.Execute()[0] 108 109 self.tree.delete(*self.tree.get_children()) 110 idx = 1 111 while not rs.EOF: 112 if self.cancel_flag: 113 break 114 raw_path = rs.Fields("System.ItemPathDisplay").Value 115 name = rs.Fields("System.FileName").Value 116 folder_path = self.get_parent_folder(raw_path) 117 self.tree.insert("", tk.END, values=(idx, name, folder_path)) 118 idx += 1 119 rs.MoveNext() 120 self.progress_var.set(idx % 100) 121 self.progress_bar.update() 122 self.progress_var.set(0) 123 except Exception as e: 124 messagebox.showerror("エラー", str(e)) 125 finally: 126 pythoncom.CoUninitialize() 127 128 def open_folder(self, event): 129 selected = self.tree.selection() 130 if not selected: 131 return 132 folder_path = self.tree.item(selected[0], "values")[2] 133 134 try: 135 resolved_path = str(Path(folder_path).resolve()) 136 print(f"[DEBUG] 開くパス: {resolved_path}") 137 if os.path.exists(resolved_path): 138 subprocess.Popen(["explorer", resolved_path], shell=True) 139 else: 140 messagebox.showinfo("情報", f"フォルダが存在しません: {resolved_path}") 141 except Exception as e: 142 messagebox.showerror("エラー", f"フォルダを開けません: {e}") 143 144if __name__ == "__main__": 145 root = tk.Tk() 146 app = WinIndexSearchApp(root) 147 root.mainloop() 148

試したこと

AIを使って何度か修正をしました。

補足情報(FW/ツールのバージョンなど)

Win11
Python 3.13.7
PowerShell

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hiroki-o

2025/08/23 02:34

このプログラムの意図としては、フォルダーとキーワードを指定したら、そのフォルダー配下でキーワードを含むファイル名をリストに出す、でよいですか? Windows 11、Python 3.13.5、pywin32 311の環境では、検索ボタンを押下しても何も出ないのでデバッグできません。
kinpati

2025/08/23 02:39

このプログラムの意図としては、フォルダーとキーワードを指定したら、そのフォルダー配下でキーワードを含むファイル名をリストに出す、でよいですか? はい、そのとおりです。 当方の環境は Win11Pro Python 3.13.7 pywin32 311 です。 検索はこちらでは出来ております。よろしくお願いいたします。
dodox86

2025/08/23 03:31 編集

> Windows 11、Python 3.13.5、pywin32 311の環境では、検索ボタンを押下しても何も出ないのでデバッグできません。 ... > 当方の環境は Win11Pro Python 3.13.7 pywin32 311 です。検索はこちらでは出来ております もしかすると、Windows自体、各個人の設定でWindows Searchのサービスを停止や無効にしていたり、検索したいフォルダーやファイルがWindows Searchのインデックス作成の対象になっていない、とかでしょうかね。そうであると、まったくヒットしない可能性もあります。 [一部修正済み]
hiroki-o

2025/08/23 04:10

なるほど、dodox86さんのおっしゃる通りに、C:\ユーザー 配下にテストフォルダーを作成したら、リストに出ました。 確かに再現しますね。これからデバッグします。 素直にglob使えばいいのに、とか思ってしまいます。
kinpati

2025/08/23 04:53

切り分けしているとどうも日本語のフォルダ名が怪しくて、下記のように無理やり追加して対応しました。 もっとスマートな方法あれば良いんですが… def normalize_path(path): translations = { "ユーザー": "Users", "ドキュメント": "Documents", "デスクトップ": "Desktop", "ダウンロード": "Downloads", "ピクチャ": "Pictures", "ビデオ": "Videos", "ミュージック": "Music" } for jp, en in translations.items(): if f"\\{jp}" in path: path = path.replace(f"\\{jp}", f"\\{en}") return path
hiroki-o

2025/08/23 05:19

その通りです。C:\ユーザーをC:\Usersに変換しないとダメです。 ctypesでWindows APIを呼び出したら変換できますが、ググるかAIに聞けば出てきます。 素直にglob(略)
bsdfan

2025/08/24 05:13

System.ItemPathDisplay ではなく System.ItemUrl を使う方法もあるようです。 (python ではないですが、ご参考 https://misohena.jp/blog/2023-04-16-windows-search-from-powershell.html ) ItemPath"Display" は表示用にローカライズされるようです。一方 ItemUrl は URL なのでパスへの変更処理がいると思いますので、どっちがいいかは場合に寄りそうですね。
guest

回答1

0

ベストアンサー

Windows 11、Python 3.13.7で確認しました。

Windows Searchを使用する方法は、他の人にまかせます。
この質問はファイル名だけで中身を見ていないので、globを使用する方法を提示します。
Windows Searchより遅い場面もあるかもしれませんが、インデックスが無くても検索できるので汎用性が高いです。

globを追加します。

import glob

97~122行目のtryの中身を、以下に置き換えます。

rs = glob.glob(f'{folder_scope}/**/*{keyword}*', recursive=True) self.tree.delete(*self.tree.get_children()) idx = 1 for raw_path in rs: if self.cancel_flag: break if not os.path.isfile(raw_path): continue folder_path = self.get_parent_folder(raw_path) self.tree.insert("", tk.END, values=(idx, raw_path, folder_path)) idx += 1 self.progress_var.set(idx % 100) self.progress_bar.update() self.progress_var.set(0)

投稿2025/08/23 06:22

hiroki-o

総合スコア1596

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kinpati

2025/08/25 00:48

レスが遅れてしまいましたが、皆様ありがとうございました。 自身の勉強にもなり大変助かりました。 また行き詰まったらここを活用していきたいと思っております。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問