| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- """
- agent67.tools.file_manager — 文件管理器
- Lambda: λ action_json. file_op(action)
- """
- import json
- import os
- import shlex
- import subprocess
- from datetime import datetime
- from pathlib import Path
- from .safety import ask_user_confirm
- def manage_file(input_json: str) -> str:
- """
- 文件系统操作。
- 支持: read / write / list / search / info / mkdir / move / delete / tree
- """
- try:
- data = json.loads(input_json)
- except json.JSONDecodeError:
- return f"❌ 无效的 JSON 输入: {input_json}"
- action = data.get("action", "")
- path = os.path.expanduser(data.get("path", ""))
- try:
- if action == "read":
- p = Path(path)
- if not p.exists():
- return f"❌ 文件不存在: {path}"
- content = p.read_text(encoding="utf-8", errors="replace")
- if len(content) > 5000:
- return content[:5000] + f"\n... (文件共 {len(content)} 字符,已截断)"
- return content
- elif action == "write":
- content = data.get("content", "")
- p = Path(path)
- p.parent.mkdir(parents=True, exist_ok=True)
- p.write_text(content, encoding="utf-8")
- return f"✅ 已写入 {path} ({len(content)} 字符)"
- elif action == "list":
- p = Path(path) if path else Path.home()
- if not p.exists():
- return f"❌ 目录不存在: {path}"
- items = sorted(p.iterdir(), key=lambda x: (not x.is_dir(), x.name))
- lines = []
- for item in items[:50]:
- prefix = "📁" if item.is_dir() else "📄"
- size = ""
- if item.is_file():
- s = item.stat().st_size
- size = f" ({s} B)" if s < 1024 else f" ({s // 1024} KB)"
- lines.append(f" {prefix} {item.name}{size}")
- header = f"📂 {p} ({len(items)} 项)"
- if len(items) > 50:
- header += " (只显示前50项)"
- return header + "\n" + "\n".join(lines)
- elif action == "search":
- pattern = data.get("pattern", "*")
- p = Path(path) if path else Path.home()
- matches = list(p.rglob(pattern))[:20]
- if not matches:
- return f"未找到匹配 '{pattern}' 的文件"
- return f"找到 {len(matches)} 个匹配:\n" + "\n".join(
- f" {m}" for m in matches
- )
- elif action == "info":
- p = Path(path)
- if not p.exists():
- return f"❌ 路径不存在: {path}"
- stat = p.stat()
- return (
- f"📋 {p.name}\n"
- f" 类型: {'目录' if p.is_dir() else '文件'}\n"
- f" 大小: {stat.st_size:,} bytes\n"
- f" 修改: {datetime.fromtimestamp(stat.st_mtime).strftime('%Y-%m-%d %H:%M:%S')}\n"
- f" 权限: {oct(stat.st_mode)[-3:]}"
- )
- elif action == "mkdir":
- Path(path).mkdir(parents=True, exist_ok=True)
- return f"✅ 目录已创建: {path}"
- elif action == "move":
- src = os.path.expanduser(data.get("src", ""))
- dst = os.path.expanduser(data.get("dst", ""))
- if not os.path.exists(src):
- return f"❌ 源路径不存在: {src}"
- os.rename(src, dst)
- return f"✅ 已移动: {src} → {dst}"
- elif action == "delete":
- if not ask_user_confirm(f"删除: {path}"):
- return "❌ 用户取消了删除操作"
- p = Path(path)
- if p.is_file():
- p.unlink()
- return f"✅ 文件已删除: {path}"
- elif p.is_dir():
- import shutil
- shutil.rmtree(path)
- return f"✅ 目录已删除: {path}"
- return f"❌ 路径不存在: {path}"
- elif action == "tree":
- depth = data.get("depth", 2)
- result = subprocess.run(
- f"find {shlex.quote(path)} -maxdepth {depth} -type f -o -type d",
- shell=True, capture_output=True, text=True, timeout=10,
- )
- return result.stdout.strip()[:3000] or f"目录为空: {path}"
- else:
- return f"❌ 未知操作: {action}. 支持: read/write/list/search/info/mkdir/move/delete/tree"
- except PermissionError:
- return f"🔒 权限不足: {path}"
- except Exception as e:
- return f"❌ 错误: {e}"
|