Okoge-keys's picture
Upload 9 files
bd01ca9 verified
import os
import re
import subprocess
import sys
from flask import Flask, render_template, request, jsonify
import PyPDF2
import docx
from pptx import Presentation
from openpyxl import load_workbook
app = Flask(__name__)
def search_files(directory, search_text, recursive=False):
"""
Search for files containing the specified text in the given directory.
Args:
directory (str): The directory path to search in
search_text (str): The text to search for
recursive (bool): Whether to search recursively in subdirectories
Returns:
list: A list of dictionaries containing file paths and matching lines
"""
results = []
# Check if directory exists
if not os.path.isdir(directory):
return {"error": f"Directory '{directory}' does not exist"}
# Create a regex pattern for fuzzy search
# This will match text with some flexibility
pattern = ''.join(f'.*?{re.escape(c)}' for c in search_text)
regex = re.compile(pattern, re.IGNORECASE)
# Walk through the directory
if recursive:
walk_func = os.walk
else:
# For non-recursive search, create a generator that only yields the top directory
def walk_func(path):
yield (path, [d for d in os.listdir(path) if os.path.isdir(os.path.join(path, d))],
[f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))])
for root, _, files in walk_func(directory):
for file in files:
file_path = os.path.join(root, file)
try:
content = ""
file_ext = os.path.splitext(file_path.lower())[1]
# PDFファイルの場合
if file_ext == '.pdf':
try:
with open(file_path, 'rb') as pdf_file:
pdf_reader = PyPDF2.PdfReader(pdf_file)
for page_num in range(len(pdf_reader.pages)):
page = pdf_reader.pages[page_num]
content += page.extract_text() + "\n"
except Exception as e:
# PDFの読み込みに失敗した場合はスキップ
continue
# Wordファイルの場合
elif file_ext == '.docx':
try:
doc = docx.Document(file_path)
for para in doc.paragraphs:
content += para.text + "\n"
# テーブル内のテキストも抽出
for table in doc.tables:
for row in table.rows:
for cell in row.cells:
content += cell.text + "\n"
except Exception as e:
# Wordファイルの読み込みに失敗した場合はスキップ
continue
# Excelファイルの場合
elif file_ext == '.xlsx':
try:
wb = load_workbook(filename=file_path, read_only=True)
for sheet_name in wb.sheetnames:
sheet = wb[sheet_name]
content += f"Sheet: {sheet_name}\n"
for row in sheet.rows:
row_text = ""
for cell in row:
if cell.value is not None:
row_text += str(cell.value) + "\t"
content += row_text + "\n"
except Exception as e:
# Excelファイルの読み込みに失敗した場合はスキップ
continue
# PowerPointファイルの場合
elif file_ext == '.pptx':
try:
prs = Presentation(file_path)
for i, slide in enumerate(prs.slides):
content += f"Slide {i+1}:\n"
for shape in slide.shapes:
if hasattr(shape, "text"):
content += shape.text + "\n"
except Exception as e:
# PowerPointファイルの読み込みに失敗した場合はスキップ
continue
else:
# 通常のテキストファイル
try:
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
except Exception as e:
# テキストファイルの読み込みに失敗した場合はスキップ
continue
# Check if the content matches the search pattern
if regex.search(content):
# Get the lines that match
lines = content.split('\n')
matching_lines = []
for i, line in enumerate(lines):
if regex.search(line):
# Add line number and content
matching_lines.append({
'line_number': i + 1,
'content': line.strip()
})
# Add to results if there are matching lines
if matching_lines:
results.append({
'file_path': file_path,
'relative_path': os.path.relpath(file_path, directory),
'matching_lines': matching_lines[:5] # Limit to first 5 matches
})
except Exception as e:
# Skip files that can't be read as text
continue
return results
@app.route('/')
def index():
return render_template('index.html')
@app.route('/search', methods=['POST'])
def search():
data = request.json
directory = data.get('directory', '')
search_text = data.get('search_text', '')
recursive = data.get('recursive', False)
if not directory or not search_text:
return jsonify({"error": "Directory and search text are required"})
results = search_files(directory, search_text, recursive)
return jsonify(results)
@app.route('/open_directory', methods=['POST'])
def open_directory():
data = request.json
file_path = data.get('file_path', '')
if not file_path:
return jsonify({"error": "ファイルパスが指定されていません"})
try:
# ファイルパスからディレクトリパスを取得
directory_path = os.path.dirname(file_path)
# ディレクトリが存在するか確認
if not os.path.isdir(directory_path):
return jsonify({"error": f"ディレクトリ '{directory_path}' が存在しません"})
# Windowsの場合、explorerを使用してディレクトリを開く
# /select,"ファイルパス" を使用すると、ファイルを選択した状態でエクスプローラーが開きます
subprocess.Popen(f'explorer.exe /select,"{file_path}"')
return jsonify({"success": True, "message": f"ディレクトリを開きました: {directory_path}"})
except Exception as e:
return jsonify({"error": f"エラーが発生しました: {str(e)}"})
@app.route('/select_folder', methods=['POST'])
def select_folder():
data = request.json
initial_dir = data.get('initial_dir', '')
try:
# スクリプトの絶対パスを取得
script_dir = os.path.dirname(os.path.abspath(__file__))
script_path = os.path.join(script_dir, 'folder_dialog.py')
# 初期ディレクトリが指定されていて、存在する場合はそれを引数として渡す
cmd_args = [sys.executable, script_path]
if initial_dir and os.path.isdir(initial_dir):
cmd_args.append(initial_dir)
# サブプロセスとしてfolder_dialog.pyを実行(新しいウィンドウで実行)
startupinfo = None
if os.name == 'nt': # Windowsの場合
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = 1 # SW_SHOWNORMAL
process = subprocess.Popen(
cmd_args,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
startupinfo=startupinfo
)
# 標準出力と標準エラー出力を取得
stdout, stderr = process.communicate()
# エラーがある場合
if stderr:
return jsonify({"error": f"エラーが発生しました: {stderr}"})
# 標準出力から選択されたフォルダパスを取得
folder_path = stdout.strip()
# フォルダが選択されなかった場合
if not folder_path:
return jsonify({"message": "フォルダ選択がキャンセルされました"})
return jsonify({"folder_path": folder_path, "message": "フォルダが選択されました"})
except Exception as e:
return jsonify({"error": f"エラーが発生しました: {str(e)}"})
if __name__ == '__main__':
app.run(debug=True)