Script python qui permet de gérer les fichiers vidéo contenus dans un répertoire et les copier vers un serveur (NAS, Xbmc,...).
Le script permet de :
- copier les films vers le serveur
- mémoriser quels films ont déjà été copiés (avec un fichier *.cfg)
- montrer quels films sont nouveaux (et donc à copier)
- gérer les noms de série tv et les copier dans le bon répertoire (nom\saison\)
Si vous encodez ou récupérez des vidéos sur votre pc régulièrement, ce script vous permet de gérer la copie de ceux-ci vers un serveur, avec un historique des copies.
Créé sur windows, avec python 3.
Source / Exemple :
#!/usr/bin/env python
# movie2server.py
# Système de gestion des films copiés vers un serveur
# 08/02/2013 v1
# python3/windows
from datetime import datetime
import os.path
import glob
import sys
import re
import shutil
chemin_films = "O:\\Films\\"
chemin_series = "O:\\Series\\"
def horodate():
"""Retourne la date et l'heure actuelle au format YYYY-MM-DD HH:MM"""
return datetime.now().strftime("%Y-%m-%d %H:%M")
class unFilm():
"""Un film. Il contient son nom, ses lieux
d'origine et destination, sa date de copie."""
def __init__(self, nom, date=" ", chemin_desti=None):
self.nom_complet = nom
self.nom_propre = "0"
self.date = date
chemin = nom.split("\\")
self.origine = "\\".join(chemin[:-1])
self.titre = chemin[-1]
self.sortie = chemin_desti
# verifions si c'est un épisode de série tv
self.tv = False
season, episode = unFilm.testSerie(self.titre)
if (season, episode) != (-1, -1):
self.season = int(season)
self.episode = int(episode)
self.tv = True
def testSerie(titre):
"""Parse le nom du fichier pour savoir
si c'est un épisode de série tv.
Renvoie True si c'est le cas."""
regex = re.compile('\D(?P<sai>\d{1,2})\D(?P<epi>\d\d)')
if regex.search(titre):
sea_epi = regex.search(titre).groups()
return [int(i) for i in sea_epi]
return [-1,-1]
def __str__(self):
if self.date == " ":
line = " "*16+"|"+self.titre
else:
line = self.date+"|"+self.titre
return line
def estRepertorie(self,sauveg):
"""Vérifie si le film est déja répertorié dans
le fichier de sauvegarde (cad a déja été copié)."""
if self.nom in sauveg.list:
return True
else:
return False
def definirSortie(self):
"""Définir le répertoire vers lequel le film sera copié."""
if self.tv: # épisode de série tv
self.nom_propre = "0"
mots_titre = re.split("\W+|_+",self.titre)[:3]
ok = 0
for serie in series: #dossiers de serie tv dispo en sortie
mots_serie = re.split("\W+|_+",serie)
for i in range(min(len(mots_serie),3)):
if mots_titre[i].lower() == mots_serie[i].lower(): ok+=1
if ok >= 1:
self.nom_propre = serie
print("! trouvé ! "+serie)
ok = 0
if self.nom_propre == "0":
self.nom_propre = input("Nom de la série: ")
self.sortie = chemin_series+self.nom_propre+"\\season "+str(self.season)+"\\"
return "serie" #indique qu'il faudra créer le répertoire de la série
if ("season "+str(self.season)) not in os.listdir(chemin_series+self.nom_propre):
return "season" #indique qu'il faudra créer le répertoire de la saison
self.sortie = chemin_series+self.nom_propre+"\\season "+str(self.season)+"\\"
return "ok"
else: #film classique
self.nom_propre = input("Nom du film : ")
self.sortie = chemin_films+self.nom_propre+"\\"
return "film" # indique qu'il faudra créer le répertoire du film
def daterNow(self):
"""Inscrit la date actuelle à côté d'un film"""
self.date = horodatage()
def copier(self):
"""Copier le film vers le répertoire de sortie."""
creer = self.definirSortie()
if creer == "serie":
os.mkdir(chemin_series+self.nom_propre)
os.mkdir(chemin_series+self.nom_propre+"\\season "+str(self.season))
if creer == "season":
os.mkdir(chemin_series+self.nom_propre+"\\season "+str(self.season))
if creer == "film":
os.mkdir(chemin_films+self.nom_propre)
ecrase = "o"
if self.titre in os.listdir(self.sortie):
ecrase = input("Fichier déjà existant, écraser? (O/n) ")
if ecrase != 'n':
print("\nDE "+self.nom_complet)
print("VERS "+self.sortie)
valide = input("ok? (O/n) ")
if valide != "n":
deb = datetime.now()
print(deb.strftime("%H:%M:%S")+" Copie en cours...")
shutil.copyfile(self.nom_complet, self.sortie+self.titre)
fin = datetime.now()
delai = fin - deb
input(fin.strftime("%H:%M:%S")+" Copie terminée en "+str(delai.seconds//60)+" minutes. (entrée)")
return
input("Ok, on ne copie pas. (entrée)")
#fin-class-unFilm------------------------------------------
class uneArchive():
"""Une archive listant des films avec leurs dates d'upload.
Elle contient un dictionnaire 'nom:date' et un booléen 'writable'
qui indique si on peut la sauvegarder dans le fichier"""
def __init__(self, file_sauv):
"""Lit le fichier de sauvegarde et le met en mémoire"""
self.list = {}
try:
with open(file_sauv,"r") as file:
brut = file.read().split("\n")
for line in brut:
if "|" in line:
date, film = line.split("|")
self.list[film] = date
print("ok fichier de sauvegarde lu.")
self.writable = True
except IOError:
print("Fichier de sauvegarde non trouvé!")
try:
with open(file_sauv,"w") as file:
input("On en crée un nouveau. (entrée)")
self.writable = True
except IOError:
print("Et impossible de le créer ici: "+file_sauv)
input("Il n'y aura pas de sauvegarde des actions faites. (entrée)")
self.writable = False
def __repr__(self):
"""Affiche le contenu de l'archive"""
bloc = []
for cle in self.list:
film = unFilm(cle, self.list[cle])
bloc.append(str(film))
return "\n".join(bloc)
def ajoute(self, titre):
"""Rajoute un film (avec la date actuelle) dans l'archive."""
nom, date = titre, horodate()
self.list[nom] = date
def enleve(self, titre):
"""Enlève un film de l'archive."""
del(self.list[titre])
def nettoyer(self, films_rep, touch):
"""Enlève de la sauvegarde les films qui ne sont plus dans le répertoire donné."""
titres_rep = [film.titre for film in films_rep]
poubelle = []
for titre_sauveg in self.list:
if titre_sauveg not in titres_rep:
poubelle.append(titre_sauveg)
for i in poubelle:
self.enleve(i)
touch += 1
if poubelle:
print("--> "+str(len(poubelle))+" films nettoyés de la sauvegarde.\n")
def sauver(self, fichier):
"""Enregistre les modifications de l'archive dans le fichier de sauvegarde."""
if self.writable:
print("MAJ Sauvegarde")
try:
with open(fichier,"w") as file:
file.write(str(self))
except IOError:
print("Erreur de sauvegarde!\nLes actions ne seront pas mémorisées.")
else:
print("Il n'est pas possible de sauvegarder, je t'avais prévenu!")
#fin-class-uneArchive----------------------------------------
def trouverSeries(chemin):
"""Renvoie les noms des séries trouvées dans le répertoire donné."""
try:
return os.listdir(chemin)
except IOError:
input("Erreur !\nAccès impossible au serveur !")
exit()
def getpath():
"""Renvoie le répertoire courant."""
if '/' in sys.argv[0]:
chemin=os.path.abspath('/'.join(sys.argv[0].split('/')[:-1]))
else:
chemin=os.getcwd()
return chemin
def getfilms(chemin):
"""Renvoie la liste des fichiers vidéo
dans le répertoire passé en argument."""
#recuperation des noms de fichiers
fichiers = []
liste = glob.glob(chemin+"\\*")
for file in liste:
if os.path.isdir(file):
fichiers.extend(getfilms(file))
else:
fichiers.append(file)
# reg expr. des extensions de films
filmext=re.compile('(avi|mkv|mp4|mpg|m4v)$')
films = [fich for fich in fichiers if filmext.search(fich)]
return films
def afficherTitre():
print("------------------------| Movie to server |-----------------------")
def afficherFilms(films, chemin):
if display == "nouveaux":
print("\nContenu de "+chemin+" :\n")
else:
print("\nNouveau contenu de "+chemin+" :\n")
print("----------------------------------------------------------------")
print("N° | Date de copie | Fichier vidéo")
print("---+------------------+-----------------------------------------")
titre_brut = [i.titre for i in films if display == "nouveaux" or i.date == " "]
date_brut = [i.date for i in films if display == "nouveaux" or i.date == " "]
n = 1
for titre in titre_brut:
print(str(n).zfill(2)+" | "+date_brut[n-1]+" | "+titre)
n += 1
print("----------------------------------------------------------------")
return titre_brut
def afficherArchive():
print("\nArchive :")
print(archive)
def daterFilms(liste, archive):
"""Récupère la date de copie pour les films
qui ont déjà été copiés précédemment (sauvegarde)."""
for film in liste:
if film.titre in archive:
film.date = archive[film.titre]
def menu(titres, archive, display, films_rep_courant):
"""Affiche le menu interactif pour l'utilisateur."""
print("\n1 - Copier vers le serveur")
print("2 - Afficher "+display)
print("3 - Déclarer comme déjà copié")
print("4 - Sauver et Quitter\n")
c = input("Choix: ")
if c == "1":
num = input("Lequel: ")
nums = [int(i) for i in re.split("\W+", num)]
for i in nums:
if i > len(titres):
return (4, display)
for elu in films_rep_courant:
if elu.titre == titres[i-1]:
elu.copier()
archive.ajoute(elu.titre)
elif c == "2":
display = switchDisplay(display)
elif c == "3": # déclarer comme déjà copié
num = input("Lequel: ")
nums = [int(i) for i in re.split("\W+", num)]
for i in nums:
if i > len(titres):
return (4, display)
elu = titres[i-1]
archive.ajoute(elu)
elif c == "4": # sauver et quitter
archive.nettoyer(films_rep_courant, touch)
if touch > 0:
archive.sauver(chemin_sauv)
else:
print("Taper 1, 2, 3 ou 4")
return (c, display)
def switchDisplay(display):
"""Bascule l'affichage entre les 'nouveaux' ou 'tout' les films."""
if display == "tout":
return "nouveaux"
else:
return "tout"
#### MAIN ####
display = "tout" # tout / nouveau par défaut
# 1. on récupère le chemin courant
chemin = getpath()
# 2. on récupère la sauvegarde
chemin_sauv = chemin+"\\movies.cfg"
archive = uneArchive(chemin_sauv)
touch = 0 #sert à verifier si l'archive change
# 3. On récupère la liste des films du répertoire courant
liste_brute = getfilms(chemin)
films_rep_courant = [unFilm(item) for item in liste_brute]
# 4. On date ceux qui sont déjà copiés
daterFilms(films_rep_courant, archive.list)
# 5. On affiche les films
os.system("cls")
afficherTitre()
affich = afficherFilms(films_rep_courant, chemin)
# 6. On récupère la liste des séries tv dispo en sortie
series = trouverSeries(chemin_series)
# 7. On affiche le menu
c = 1
while c != "4":
c, display = menu(affich, archive, display, films_rep_courant)
if c == "1" or c == "2" or c =="3":
os.system("cls")
afficherTitre()
if c != 2:
daterFilms(films_rep_courant, archive.list)
touch += 1
affich = afficherFilms(films_rep_courant, chemin)
print("\n--fin")
#--EOF
Conclusion :
Nécessite de connecter le serveur en tant que lecteur réseau (sur windows) et d'adapter les variables chemin_films et chemin_series pour les faire pointer vers ce lecteur réseau.
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.