#!/usr/bin/env python3 import sys import os import shutil from pathlib import Path from guessit import guessit MEDIA = Path("/data/media") JULY = Path("/data/july") DRY_RUN = "--dry-run" in sys.argv VIDEO_EXTENSIONS = {'.mkv', '.mp4', '.avi', '.mov', '.wmv', '.m4v', '.ts', '.m2ts'} def log(action, src, dst): if DRY_RUN: print(f"[DRY-RUN] {action}: {src} → {dst}") else: print(f"[{action}] {src} → {dst}") def hardlink_tree(src: Path, dst: Path): dst.mkdir(parents=True, exist_ok=True) if src.is_file(): target = dst / src.name if not target.exists(): if not DRY_RUN: os.link(src, target) else: print(f"[SKIP] уже существует: {target}") elif src.is_dir(): for f in src.iterdir(): if f.is_file(): target = dst / f.name if not target.exists(): if not DRY_RUN: os.link(f, target) else: print(f"[SKIP] уже существует: {target}") def process(src: Path): name = src.name # Пропускаем не видео if src.is_file() and src.suffix.lower() not in VIDEO_EXTENSIONS: print(f"[SKIP] не видео: {name}") return # Для папок — проверяем есть ли внутри видео файлы if src.is_dir(): has_video = any( f.suffix.lower() in VIDEO_EXTENSIONS for f in src.rglob("*") if f.is_file() ) if not has_video: print(f"[SKIP] нет видео файлов: {name}") return info = guessit(name) info = guessit(name) kind = info.get("type") title = info.get("title", name) year = info.get("year") season = info.get("season") if kind == "movie": folder_name = f"{title} ({year})" if year else title dst = JULY / "Фильмы" / folder_name log("MOVIE", src, dst) hardlink_tree(src, dst) elif kind == "episode": season_str = f"Season {season:02d}" if season else "Season 01" dst = JULY / "Сериалы" / title / season_str log("SERIES", src, dst) hardlink_tree(src, dst) else: print(f"[SKIP] не распознан: {name}") def main(): args = [a for a in sys.argv[1:] if not a.startswith("--")] if len(args) == 0: # Автоскан всего /data/media for item in sorted(MEDIA.iterdir()): process(item) elif len(args) == 1: # Один элемент — полный путь или имя src = Path(args[0]) if not src.is_absolute(): src = MEDIA / src process(src) elif len(args) == 2: # Вручную: источник + категория/название src = Path(args[0]) if not src.is_absolute(): src = MEDIA / src dst = JULY / args[1] log("MANUAL", src, dst) hardlink_tree(src, dst) else: print("Использование:") print(" linkmedia [--dry-run] # автоскан") print(" linkmedia [--dry-run] # один элемент") print(" linkmedia [--dry-run] <Категория/папка> # вручную") if __name__ == "__main__": main()