Automatizace v Pythonu: třídění souborů, zálohy a spouštění cronem
Python skripty pro úklid složky se staženými soubory, rotaci záloh a hromadné přejmenování – a jejich spouštění přes cron nebo systemd timer.
Opakující se práci se soubory je škoda dělat ručně. V tomto článku napíšeme tři užitečné skripty pomocí pathlib a shutil a ukážeme, jak je spolehlivě spouštět automaticky – včetně chyb, na které cron rád upozorní až po týdnu.
Základ: pathlib místo os.path
from pathlib import Path
slozka = Path.home() / "Stažené"
for soubor in slozka.iterdir():
if soubor.is_file():
print(soubor.name, soubor.suffix, soubor.stat().st_size)
list(slozka.glob("*.pdf")) # PDF v této složce
list(slozka.rglob("*.jpg")) # JPG rekurzivně
Operátor / skládá cesty bez starostí o lomítka a funguje stejně na Linuxu i Windows.
Skript 1: třídění složky podle přípony
#!/usr/bin/env python3
import shutil
from pathlib import Path
ZDROJ = Path.home() / "Stažené"
PRAVIDLA = {
"Dokumenty": {".pdf", ".docx", ".xlsx", ".odt", ".txt"},
"Obrázky": {".jpg", ".jpeg", ".png", ".gif", ".webp"},
"Archivy": {".zip", ".tar", ".gz", ".7z"},
"Instalátory": {".deb", ".exe", ".msi", ".dmg"},
}
def cil_pro(pripona: str) -> str | None:
for slozka, pripony in PRAVIDLA.items():
if pripona.lower() in pripony:
return slozka
return None
def volne_jmeno(cesta: Path) -> Path:
"""Když soubor existuje, přidá (1), (2)…"""
if not cesta.exists():
return cesta
i = 1
while True:
kandidat = cesta.with_name(f"{cesta.stem} ({i}){cesta.suffix}")
if not kandidat.exists():
return kandidat
i += 1
for soubor in ZDROJ.iterdir():
if not soubor.is_file():
continue
slozka = cil_pro(soubor.suffix)
if slozka is None:
continue
cil = ZDROJ / slozka
cil.mkdir(exist_ok=True)
shutil.move(soubor, volne_jmeno(cil / soubor.name))
print(f"{soubor.name} → {slozka}/")
Funkce volne_jmeno řeší nejčastější problém: přesun by jinak tiše přepsal stejnojmenný soubor.
Skript 2: záloha s rotací
Zabalí adresář do .tar.gz s datem v názvu a ponechá posledních N záloh:
#!/usr/bin/env python3
import shutil
from datetime import datetime
from pathlib import Path
ZDROJ = Path("/var/www/muj-web")
CIL = Path("/var/backups/muj-web")
PONECHAT = 7
CIL.mkdir(parents=True, exist_ok=True)
nazev = CIL / f"web-{datetime.now():%Y-%m-%d_%H%M}"
archiv = shutil.make_archive(str(nazev), "gztar", root_dir=ZDROJ)
print("Vytvořeno:", archiv)
zalohy = sorted(CIL.glob("web-*.tar.gz"))
for stara in zalohy[:-PONECHAT]:
stara.unlink()
print("Smazáno:", stara.name)
Řazení podle jména funguje díky formátu data RRRR-MM-DD. Proto datum v názvech souborů vždy pište takto.
Skript 3: hromadné přejmenování s náhledem
#!/usr/bin/env python3
import re
import sys
from pathlib import Path
slozka = Path(sys.argv[1])
provest = "--ok" in sys.argv
for i, f in enumerate(sorted(slozka.glob("*.jpg")), start=1):
nove = f.with_name(f"dovolena-{i:03d}{f.suffix.lower()}")
print(f"{f.name} → {nove.name}")
if provest:
f.rename(nove)
if not provest:
print("\nNanečisto. Spusťte s --ok pro provedení.")
Režim „nanečisto“ je u destruktivních skriptů zlaté pravidlo.
Spouštění přes cron
Skript udělejte spustitelný a otevřete crontab:
chmod +x ~/skripty/zaloha.py
crontab -e
# min hod den měs dvt příkaz
30 2 * * * /usr/bin/python3 /home/jan/skripty/zaloha.py >> /home/jan/logs/zaloha.log 2>&1
*/15 * * * * /home/jan/projekt/.venv/bin/python /home/jan/projekt/uklid.py
Proč skript v cronu nefunguje, i když ručně ano
- Jiné prostředí. Cron má minimální
PATHa neaktivuje virtuální prostředí. Volejte přímo interpret z venv:/cesta/.venv/bin/python. - Relativní cesty. Pracovní adresář je domovská složka, ne složka skriptu. V kódu používejte
Path(__file__).resolve().parent. - Výstup mizí. Bez přesměrování
>> log 2>&1cron výstup posílá e-mailem (pokud je nastaven) nebo zahodí. Chybu pak nikdy neuvidíte. - Znak
%má v crontabu zvláštní význam (nový řádek) a musí se escapovat\%. Datum generujte raději v Pythonu.
Ověření, že cron úlohu spustil:
grep CRON /var/log/syslog # Debian/Ubuntu
journalctl -u cron --since today
Alternativa: systemd timer
Na serveru se systemd je timer často lepší volba: logy jdou do journalu, úloha se dá spustit ručně a s Persistent=true se dožene, pokud byl počítač v daný čas vypnutý.
/etc/systemd/system/zaloha.service:
[Unit]
Description=Záloha webu
[Service]
Type=oneshot
User=jan
ExecStart=/usr/bin/python3 /home/jan/skripty/zaloha.py
/etc/systemd/system/zaloha.timer:
[Unit]
Description=Denní záloha webu
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now zaloha.timer
systemctl list-timers
sudo systemctl start zaloha.service # ruční spuštění pro test
journalctl -u zaloha.service -n 50
Pojistky pro automatické skripty
- Před mazáním vždy logujte, co se maže.
- Ošetřete souběh: když předchozí běh ještě neskončil, nový by neměl začít. V cronu pomůže
flock -n /tmp/zaloha.lock python3 zaloha.py. - Zálohy občas zkuste obnovit. Záloha, kterou nikdo nezkoušel rozbalit, je jen naděje.
Pokud máte VPS připojený k ColdHost AI, můžete v režimu Server a DevOps nechat AI timer vytvořit – navržené příkazy uvidíte a každý schválíte, než se spustí.