148 lines
5.2 KiB
Python
Executable File
148 lines
5.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
monitor_transfer.py
|
||
===================
|
||
Фоновый мониторинг переноса архива со смартфона.
|
||
Каждые 3 секунды обновляет файл прогресса на Рабочем столе:
|
||
/home/alexives/Desktop/ПРОГРЕСС_ПЕРЕНОСА.txt
|
||
и короткую строку:
|
||
/home/alexives/Desktop/ПРОГРЕСС_СТРОКА.txt
|
||
"""
|
||
|
||
import os
|
||
import sys
|
||
import time
|
||
import subprocess
|
||
from pathlib import Path
|
||
|
||
DEST_ROOT = Path("/mnt/data/архив_с_телефона")
|
||
DESKTOP_FULL = Path("/home/alexives/Desktop/ПРОГРЕСС_ПЕРЕНОСА.txt")
|
||
DESKTOP_LINE = Path("/home/alexives/Desktop/ПРОГРЕСС_СТРОКА.txt")
|
||
|
||
# Целевые объемы в байтах
|
||
TARGET_SIZES = {
|
||
"Download": 17 * 1024 * 1024 * 1024,
|
||
"футажи": 2.3 * 1024 * 1024 * 1024,
|
||
"Pictures": 1.4 * 1024 * 1024 * 1024,
|
||
"DCIM/MyAlbums": 59 * 1024 * 1024 * 1024,
|
||
"DCIM/Camera": 16 * 1024 * 1024 * 1024,
|
||
}
|
||
TOTAL_BYTES = sum(TARGET_SIZES.values())
|
||
|
||
def get_dir_size(path: Path) -> int:
|
||
if not path.exists():
|
||
return 0
|
||
try:
|
||
res = subprocess.run(["du", "-sb", str(path)], capture_output=True, text=True, check=True)
|
||
return int(res.stdout.split()[0])
|
||
except Exception:
|
||
return 0
|
||
|
||
def format_size(bytes_val: int) -> str:
|
||
gb = bytes_val / (1024 ** 3)
|
||
if gb >= 1.0:
|
||
return f"{gb:.2f} ГБ"
|
||
mb = bytes_val / (1024 ** 2)
|
||
return f"{mb:.1f} МБ"
|
||
|
||
def make_bar(percent: float, length: int = 25) -> str:
|
||
filled = int(round(length * percent / 100))
|
||
filled = max(0, min(length, filled))
|
||
return "█" * filled + "░" * (length - filled)
|
||
|
||
def main():
|
||
prev_bytes = 0
|
||
prev_time = time.time()
|
||
speed = 0.0
|
||
|
||
while True:
|
||
current_sizes = {}
|
||
total_copied = 0
|
||
|
||
for name in TARGET_SIZES:
|
||
sz = get_dir_size(DEST_ROOT / name)
|
||
current_sizes[name] = sz
|
||
total_copied += sz
|
||
|
||
now = time.time()
|
||
dt = now - prev_time
|
||
if dt >= 2.0:
|
||
if prev_bytes > 0 and total_copied >= prev_bytes:
|
||
speed = (total_copied - prev_bytes) / dt
|
||
prev_bytes = total_copied
|
||
prev_time = now
|
||
|
||
percent = (total_copied / TOTAL_BYTES) * 100
|
||
percent = min(100.0, percent)
|
||
|
||
# Определение текущей активной папки
|
||
current_folder = "Завершено"
|
||
for name in TARGET_SIZES:
|
||
target = TARGET_SIZES[name]
|
||
curr = current_sizes[name]
|
||
if curr < target * 0.98:
|
||
current_folder = name
|
||
break
|
||
|
||
speed_mb = speed / (1024 * 1024)
|
||
rem_bytes = max(0, TOTAL_BYTES - total_copied)
|
||
eta_min = (rem_bytes / speed / 60) if speed > 100000 else 0
|
||
|
||
bar = make_bar(percent, 25)
|
||
now_str = time.strftime("%H:%M:%S")
|
||
|
||
# 1. Формируем подробный отчет
|
||
full_report = [
|
||
"=" * 68,
|
||
" 📱 СТАТУС ПЕРЕНОСА АРХИВА СО СМАРТФОНА",
|
||
"=" * 68,
|
||
f"Прогресс: [{bar}] {percent:.1f}%",
|
||
f"Объём: {format_size(total_copied)} из ~{format_size(TOTAL_BYTES)}",
|
||
f"Скорость: {speed_mb:.1f} МБ/сек",
|
||
f"Осталось: ~{eta_min:.0f} мин." if eta_min > 0 else "Осталось: расчёт...",
|
||
f"Текущая: «{current_folder}»",
|
||
"-" * 68,
|
||
"📂 Статус папок:",
|
||
]
|
||
|
||
for name, target in TARGET_SIZES.items():
|
||
curr = current_sizes[name]
|
||
if curr == 0:
|
||
st = "[В ОЧЕРЕДИ]"
|
||
elif curr >= target * 0.98:
|
||
st = "[ГОТОВО]"
|
||
else:
|
||
st = "[КОПИРУЕТСЯ...]"
|
||
full_report.append(f" • {name:<14} {st:<16} {format_size(curr)} / {format_size(target)}")
|
||
|
||
full_report.append("-" * 68)
|
||
full_report.append(" (Музыка и аудиокниги оставлены на телефоне)")
|
||
full_report.append(f"Обновлено: {now_str}")
|
||
full_report.append("=" * 68)
|
||
|
||
# 2. Формируем короткую строку состояния
|
||
one_line = f"[{bar}] {percent:.1f}% | {format_size(total_copied)} / {format_size(TOTAL_BYTES)} | {speed_mb:.1f} МБ/с | ETA: ~{eta_min:.0f}м | Папка: {current_folder} ({now_str})\n"
|
||
|
||
# Запись файлов
|
||
try:
|
||
with open(DESKTOP_FULL, "w", encoding="utf-8") as f:
|
||
f.write("\n".join(full_report) + "\n")
|
||
with open(DESKTOP_LINE, "w", encoding="utf-8") as f:
|
||
f.write(one_line)
|
||
except Exception:
|
||
pass
|
||
|
||
# Проверка завершения
|
||
if percent >= 99.9:
|
||
try:
|
||
subprocess.run(["notify-send", "Архив с телефона", "Все файлы успешно перенесены на компьютер!"])
|
||
except Exception:
|
||
pass
|
||
break
|
||
|
||
time.sleep(3)
|
||
|
||
if __name__ == "__main__":
|
||
main()
|