delete_old_aos.iso
· 3.2 KiB · Text
原始檔案
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
按分支(1.0、1.1、1.2、1.3…)仅保留该分支中“最高版本目录”的 .iso 文件,删除其余版本目录中的 .iso。
- 仅删除 .iso,不动 .sha256 / .torrent / 目录结构。
- 支持 --dry-run 仅打印计划删除项。
- 版本比较使用语义数字比较:x.y.z -> (x,y,z),保证 1.3.10 > 1.3.4。
"""
from __future__ import annotations
import argparse
import logging
from pathlib import Path
import re
from typing import List, Tuple
BRANCH_RE = re.compile(r"^\d+\.\d+$") # e.g. "1.3"
VERSION_RE = re.compile(r"^\d+\.\d+\.\d+$") # e.g. "1.3.4"
def parse_version_tuple(s: str) -> Tuple[int, int, int]:
try:
a, b, c = s.split(".")
return int(a), int(b), int(c)
except Exception:
raise ValueError(f"非法版本号: {s}")
def find_branches(root: Path) -> List[Path]:
return sorted([p for p in root.iterdir() if p.is_dir() and BRANCH_RE.match(p.name)])
def find_versions(branch_dir: Path) -> List[Path]:
# 仅考虑该分支下的直接子目录,且匹配 x.y.z
return sorted([p for p in branch_dir.iterdir() if p.is_dir() and VERSION_RE.match(p.name)],
key=lambda p: parse_version_tuple(p.name))
def delete_old_isos(root: Path, dry_run: bool = True) -> int:
"""
返回计划/删除的 .iso 数量。
"""
total = 0
for branch in find_branches(root):
versions = find_versions(branch)
if not versions:
logging.info("分支 %s 无版本子目录,跳过。", branch)
continue
latest = versions[-1] # 最高版本
logging.info("分支 %s => 保留最新版本目录: %s", branch.name, latest.name)
# 其它版本目录中的 .iso 需要删除
to_clean = [v for v in versions if v != latest]
for vdir in to_clean:
for iso in vdir.glob("*.iso"):
total += 1
if dry_run:
logging.info("[DRY-RUN] 将删除: %s", iso)
else:
try:
iso.unlink()
logging.info("已删除: %s", iso)
except Exception as e:
logging.error("删除失败: %s (%s)", iso, e)
return total
def main():
ap = argparse.ArgumentParser(
description="按分支仅保留最新版本目录中的 .iso 文件,其余版本目录的 .iso 将被删除。"
)
ap.add_argument("root", nargs="?", default=".", help="根目录(默认为当前目录)")
ap.add_argument("--dry-run", "-n", action="store_true", help="只演练,不真正删除")
ap.add_argument("--quiet", "-q", action="store_true", help="安静模式,仅报错")
args = ap.parse_args()
log_level = logging.ERROR if args.quiet else logging.INFO
logging.basicConfig(level=log_level, format="%(message)s")
root = Path(args.root).resolve()
if not root.exists() or not root.is_dir():
logging.error("无效目录:%s", root)
raise SystemExit(2)
count = delete_old_isos(root, dry_run=args.dry_run)
if args.dry_run:
print(f"[DRY-RUN] 计划删除 .iso 数量: {count}")
else:
print(f"已删除 .iso 数量: {count}")
if __name__ == "__main__":
main()
1 | #!/usr/bin/env python3 |
2 | # -*- coding: utf-8 -*- |
3 | |
4 | """ |
5 | 按分支(1.0、1.1、1.2、1.3…)仅保留该分支中“最高版本目录”的 .iso 文件,删除其余版本目录中的 .iso。 |
6 | - 仅删除 .iso,不动 .sha256 / .torrent / 目录结构。 |
7 | - 支持 --dry-run 仅打印计划删除项。 |
8 | - 版本比较使用语义数字比较:x.y.z -> (x,y,z),保证 1.3.10 > 1.3.4。 |
9 | """ |
10 | |
11 | from __future__ import annotations |
12 | import argparse |
13 | import logging |
14 | from pathlib import Path |
15 | import re |
16 | from typing import List, Tuple |
17 | |
18 | BRANCH_RE = re.compile(r"^\d+\.\d+$") # e.g. "1.3" |
19 | VERSION_RE = re.compile(r"^\d+\.\d+\.\d+$") # e.g. "1.3.4" |
20 | |
21 | def parse_version_tuple(s: str) -> Tuple[int, int, int]: |
22 | try: |
23 | a, b, c = s.split(".") |
24 | return int(a), int(b), int(c) |
25 | except Exception: |
26 | raise ValueError(f"非法版本号: {s}") |
27 | |
28 | def find_branches(root: Path) -> List[Path]: |
29 | return sorted([p for p in root.iterdir() if p.is_dir() and BRANCH_RE.match(p.name)]) |
30 | |
31 | def find_versions(branch_dir: Path) -> List[Path]: |
32 | # 仅考虑该分支下的直接子目录,且匹配 x.y.z |
33 | return sorted([p for p in branch_dir.iterdir() if p.is_dir() and VERSION_RE.match(p.name)], |
34 | key=lambda p: parse_version_tuple(p.name)) |
35 | |
36 | def delete_old_isos(root: Path, dry_run: bool = True) -> int: |
37 | """ |
38 | 返回计划/删除的 .iso 数量。 |
39 | """ |
40 | total = 0 |
41 | for branch in find_branches(root): |
42 | versions = find_versions(branch) |
43 | if not versions: |
44 | logging.info("分支 %s 无版本子目录,跳过。", branch) |
45 | continue |
46 | |
47 | latest = versions[-1] # 最高版本 |
48 | logging.info("分支 %s => 保留最新版本目录: %s", branch.name, latest.name) |
49 | |
50 | # 其它版本目录中的 .iso 需要删除 |
51 | to_clean = [v for v in versions if v != latest] |
52 | for vdir in to_clean: |
53 | for iso in vdir.glob("*.iso"): |
54 | total += 1 |
55 | if dry_run: |
56 | logging.info("[DRY-RUN] 将删除: %s", iso) |
57 | else: |
58 | try: |
59 | iso.unlink() |
60 | logging.info("已删除: %s", iso) |
61 | except Exception as e: |
62 | logging.error("删除失败: %s (%s)", iso, e) |
63 | |
64 | return total |
65 | |
66 | def main(): |
67 | ap = argparse.ArgumentParser( |
68 | description="按分支仅保留最新版本目录中的 .iso 文件,其余版本目录的 .iso 将被删除。" |
69 | ) |
70 | ap.add_argument("root", nargs="?", default=".", help="根目录(默认为当前目录)") |
71 | ap.add_argument("--dry-run", "-n", action="store_true", help="只演练,不真正删除") |
72 | ap.add_argument("--quiet", "-q", action="store_true", help="安静模式,仅报错") |
73 | args = ap.parse_args() |
74 | |
75 | log_level = logging.ERROR if args.quiet else logging.INFO |
76 | logging.basicConfig(level=log_level, format="%(message)s") |
77 | |
78 | root = Path(args.root).resolve() |
79 | if not root.exists() or not root.is_dir(): |
80 | logging.error("无效目录:%s", root) |
81 | raise SystemExit(2) |
82 | |
83 | count = delete_old_isos(root, dry_run=args.dry_run) |
84 | if args.dry_run: |
85 | print(f"[DRY-RUN] 计划删除 .iso 数量: {count}") |
86 | else: |
87 | print(f"已删除 .iso 数量: {count}") |
88 | |
89 | if __name__ == "__main__": |
90 | main() |
91 |