sync from WSL host: latest openclaw config update
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
按规则分类归档 source_dirs 中的目录到 categories 定义的大类目录
|
||||
读配置文件:与脚本同目录下的 config.json
|
||||
"""
|
||||
import os, json, shutil
|
||||
|
||||
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
def load_config():
|
||||
cfg_path = os.path.join(SCRIPT_DIR, "..", "config.json")
|
||||
with open(cfg_path) as f:
|
||||
return json.load(f)
|
||||
|
||||
def classify(name, cfg):
|
||||
"""返回目标目录路径,或 None(不移动)"""
|
||||
if name in cfg.get("keep_as_is", []):
|
||||
return None
|
||||
for cat in cfg["categories"]:
|
||||
keywords = cat["keywords"]
|
||||
if any(k in name for k in keywords):
|
||||
return cat["dir"]
|
||||
fallback = cfg.get("fallback_dir")
|
||||
if fallback:
|
||||
return fallback
|
||||
return None
|
||||
|
||||
def main():
|
||||
cfg = load_config()
|
||||
src_dirs = cfg["source_dirs"]
|
||||
|
||||
moves = []
|
||||
for base in src_dirs:
|
||||
if not os.path.isdir(base):
|
||||
print(f" [WARN] 目录不存在: {base}")
|
||||
continue
|
||||
for entry in sorted(os.listdir(base)):
|
||||
full = os.path.join(base, entry)
|
||||
if not os.path.isdir(full):
|
||||
continue
|
||||
dst_base = classify(entry, cfg)
|
||||
if dst_base is None:
|
||||
print(f" ○ 不动: {entry}")
|
||||
continue
|
||||
dst = os.path.join(dst_base, entry)
|
||||
if os.path.exists(dst):
|
||||
i = 1
|
||||
while os.path.exists(f"{dst}_{i}"): i += 1
|
||||
dst = f"{dst}_{i}"
|
||||
moves.append((full, dst))
|
||||
|
||||
# 创建目录
|
||||
for _, d in moves:
|
||||
os.makedirs(os.path.dirname(d), exist_ok=True)
|
||||
|
||||
# 执行移动
|
||||
print(f"开始移动 {len(moves)} 个条目...")
|
||||
for src, dst in moves:
|
||||
try:
|
||||
shutil.move(src, dst)
|
||||
print(f" ✓ {os.path.basename(src)}")
|
||||
except Exception as e:
|
||||
print(f" ✗ {os.path.basename(src)} -> {e}")
|
||||
|
||||
# 清理空源目录
|
||||
for d in src_dirs:
|
||||
if os.path.isdir(d) and not os.listdir(d):
|
||||
os.rmdir(d)
|
||||
print(f" ✓ 已删空目录: {d}")
|
||||
|
||||
# 报告
|
||||
base = os.path.commonpath([os.path.dirname(d) for _, d in moves])
|
||||
for _, d in moves:
|
||||
base = os.path.commonpath([base, os.path.dirname(d)])
|
||||
base = base or "/"
|
||||
|
||||
print(f"\n=== 归档完成 ===")
|
||||
seen = set()
|
||||
for _, d in moves:
|
||||
parent = os.path.dirname(d)
|
||||
if parent not in seen:
|
||||
sz = 0
|
||||
cnt = 0
|
||||
for dp, dn, fn in os.walk(parent):
|
||||
for f in fn:
|
||||
cnt += 1
|
||||
try: sz += os.path.getsize(os.path.join(dp, f))
|
||||
except: pass
|
||||
print(f" {parent}/ ({cnt} 文件, {sz/1024**3:.1f}GB)")
|
||||
seen.add(parent)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
扫描 + 清理垃圾
|
||||
遍历 source_dirs,清理空壳目录和小视频残片
|
||||
读配置文件:与脚本同目录下的 config.json
|
||||
"""
|
||||
import os, json, sys
|
||||
|
||||
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
def load_config():
|
||||
cfg_path = os.path.join(SCRIPT_DIR, "..", "config.json")
|
||||
with open(cfg_path) as f:
|
||||
return json.load(f)
|
||||
|
||||
def scan_and_clean(cfg):
|
||||
src_dirs = cfg["source_dirs"]
|
||||
min_size = cfg["min_size_mb"] * 1024 * 1024
|
||||
video_exts = {'.mp4','.mkv','.avi','.mov','.wmv','.flv','.webm','.ts','.m4v','.rmvb'}
|
||||
|
||||
targets = []
|
||||
print("=== 扫描 ===")
|
||||
for base in src_dirs:
|
||||
if not os.path.isdir(base):
|
||||
print(f" [WARN] 目录不存在: {base}")
|
||||
continue
|
||||
for entry in sorted(os.listdir(base)):
|
||||
full = os.path.join(base, entry)
|
||||
if not os.path.isdir(full):
|
||||
continue
|
||||
total_sz = 0
|
||||
real_video = 0
|
||||
try:
|
||||
for dp, dn, fn in os.walk(full):
|
||||
for f in fn:
|
||||
fp = os.path.join(dp, f)
|
||||
try:
|
||||
total_sz += os.path.getsize(fp)
|
||||
except: pass
|
||||
if os.path.splitext(f)[1].lower() in video_exts:
|
||||
real_video += 1
|
||||
except: pass
|
||||
|
||||
action = "KEEP"
|
||||
if total_sz < min_size and real_video == 0:
|
||||
action = "DELETE"
|
||||
elif total_sz < min_size and real_video > 0:
|
||||
action = "DELETE"
|
||||
|
||||
print(f" [{action:>6}] {entry} ({total_sz/1024**2:.0f}MB, {real_video}视频)")
|
||||
|
||||
if action == "DELETE":
|
||||
targets.append(full)
|
||||
|
||||
if targets:
|
||||
print(f"\n待删除: {len(targets)} 个")
|
||||
print("开始删除...")
|
||||
import shutil
|
||||
for d in targets:
|
||||
shutil.rmtree(d)
|
||||
print(f" ✓ 已删: {os.path.basename(d)}")
|
||||
else:
|
||||
print("\n无需清理。")
|
||||
|
||||
if __name__ == "__main__":
|
||||
cfg = load_config()
|
||||
scan_and_clean(cfg)
|
||||
Reference in New Issue
Block a user