Add NAS config files
This commit is contained in:
Executable
+114
@@ -0,0 +1,114 @@
|
||||
#!/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] <src> # один элемент")
|
||||
print(" linkmedia [--dry-run] <src> <Категория/папка> # вручную")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user