AnsuzPeorth a écritOui, python serai une idée, ce qui est plus simple avec bash, c'est l'accès à des outils comme tail, head, grep, join, cut que je ne suis pas sur de retrouver dans python.
Ah, c'est sur, tu ne trouveras plus ce genre d'outils, c'est beaucoup plus simple en python.
(...)
Il faudrait que je me documente un peu sur python, ca pourrais m'être utile par la suite de toute manière.
Python est plus simple que bash je pense (pour une utilisation simple), par contre la POO, les classes, self, héritages & co, au début c'est un peu galère, mais après, quand on découvre la puissance ...
janvier42 a écrit
Salut,
Super initiative, je trouve que c'est une bonne idée pour pouvoir facilement installer toutes ses applications en cas de réinstallation du système ou mise à jour de la version d'ubuntu.
Je voulais juste savoir où en était ton projet d'écriture du programme en python ?
J'ai (enfin) fais une version en python
J'ai implémenté une logique très similaire, il manque que 2 chose à la version en python : les colonnes ne sont pas aligné dans l'affichage des résultats, et il n'y a pas l'option -s.
Voici ce que j'en ai retenu :
* Python légèrement plus rapide (python : 5.4 s, bash : 8 secondes)
* Taille de Code sensiblement identique
* Code python beaucoup plus lisible !
* Code python sûrement plus extensible !
* Logique code complètement différente !
Voici les 2 bases de code :
Bash :
#!/bin/bash
# Développeur : Quentin Bérard : dev@quent.fr
# Licence Creativ Common BY - SA http://creativecommons.org/licenses/by-sa/2.0/fr/ ou GPL v3
# version 1.3.0
# diff 1.2 et 1.3 passage à apt-mark showmanual
# diff 1.1 et 1.2 ajout de la ligne de commande -s, parcours de tous les /var/log/dpkg.log affichage de l'alphabet pour attendre
# diff 1.0 et 1.1 : beaucoup plus rapide, utilisation de join, affichage catégorie
# TODO :
# - supprimer la dépendance à aptitude
# - utiliser : /var/lib/apt/extended_states
# - vérifier si on trouve les mêmes résultats
# - arriver à parser le fichier.
# - comportement après une maj de version de l'OS ?
# - améliorer la rapidité du script
# - remplacer apt-cache show par plus rapide
# - filtrer les paquets linux-image et linux-headers
# - supprimer cat quand c'est possible (suivi de grep)
# Notes :
# Lister les paquets installés :
# - dpkg -l
# - dpkg --get-selections
# Info sur paquet
# - apt-cache show paquet
# - dpkg --print-avail paquet
# Liste les paquets installés manuellements :
# - apt-mark showmanual
# - aptitude search '~i !~M' -F '%p'
# cat t1 | sort -k 3 : trier suivant la 3eme colonne
verbose=true
if (( $# >= 1 ));
then
if [ $1 = "-s" ];
then
verbose=false
fi
fi
# adresse de base du fichier des logs.
log="/var/log/dpkg.log"
# on affiche d'abord les logs en gz (2-x) dans l'ordre inverse (x-2) puis les autres (.1 et néant) dans l'ordre inverse.
# on ne récupere que les ligne concernant une installation.
leslogs=$(echo -e "$(gunzip $(ls $log*.gz | sort -r ) --stdout ; cat $(ls $log* | grep -v ".gz" | sort -r ))" | grep "\ install\ ")
#la premiere entrée correspond forcément à un paquet installé par défaut lors de l'instal de l'Ubuntu.
#on récupère alors sa date d'installation.
dateInstal=$(echo "$leslogs" | head -1 | cut -d" " -f1)
#toute les dates d'installations, on ne prend que les colonnes intéressantes
allPackagesDate=$(echo "$leslogs" | cut -d" " -f1,2,4)
#tout les noms (-F '%p') des paquets installés (i) non automatiquement (!M)
packages=$(apt-mark showmanual)
if $verbose ;
then
echo "Liste des paquets installés manuellement, et après l'installation de l'OS :"
echo "Attendez 2 minutes !"
fi
liste=""
l=""
allPackagesDate=$(echo "$allPackagesDate" | grep -v "$dateInstal" )
#les - ne sont pas triés pareil
echo "$packages" | sort -k 1 > .doesntExistinstalledPackages
# tri sur la colonne des paquets
echo "$allPackagesDate" | sort -k 3 > .doesntExistdatedPackages
# jointure
join -1 1 -2 3 ".doesntExistinstalledPackages" ".doesntExistdatedPackages" | tee ".doesntExistinstalledDatedPackages" >> "/dev/null"
#affiche la catégorie de l'arg1 sur la sortie
getCategory() {
package=$1
# propriétés du package, partie Section, afficher une seul ligne (souvent répété cf liboverlay-scrollbar-0.1-0)
# puis enlever "Section: "
cat=$(apt-cache show $package | grep "Section: " | head -1 | cut -d" " -f2)
cat2=$(echo $cat | cut -d"/" -f2) #Section: universe/graphics
if [ -z cat2 ];
then # si "graphics"
cat2=$cat
fi
echo "$cat2"
}
cat=""
liste=""
lastPackage=""
lastPackageLine=""
OLDIFS=$IFS
lettre=""
IFS='
'
for arg in $(cat .doesntExistinstalledDatedPackages)
do
IFS=$OLDIFS # pour ne pas poluer le reste du programme
# uniquement le nom
package=$(echo "$arg" | cut -d" " -f1)
# si le nom n'est pas nouveau, on n'affiche pas le dernier
# si le nom est nouveau, on affiche le précédent
if [ ! "$package" = "$lastPackage" ];
then
# pas le premier
if [ ! $lastPackage = "" ];
then
if $verbose ;
then
# on recherche la catégorie
cat=$(getCategory $lastPackage)
fi
# on ajoute a la liste
liste=$(echo "$liste\n$cat $lastPackageWithDate")
fi
fi
# on garde mémoire du dernier package avec la date
lastPackageWithDate=$arg
# on garde la mémoire du dernier package
lastPackage=$package
#affichage de l'alphabet d'attente
if $verbose ;
then
flettre=$(echo $package | head -c 1)
if [ ! "$lettre" = "$flettre" ];
then
echo -n "$flettre"
lettre=$flettre
fi
fi
#pour le prochain tours de for
IFS='
'
done
## on ajoute le dernier. ##
# on recherche la catégorie
if $verbose ;
then
#apres l'alphabet : un espace
echo
echo
cat=$(getCategory $lastPackage)
fi
# on ajoute a la liste
liste=$(echo "$liste\n$cat $lastPackageWithDate")
if ! $verbose ;
then
# on passe le " " initiale
liste=$(echo -e "$liste" | cut -d" " -f2)
# plusieurs colonnes
liste=$(echo -e "$liste" | column)
else
#trie suivant la catégorie
liste=$(echo -e "$liste" | sort)
#mise en colonne
liste=$(echo -e "$liste" | column -t)
#affichage
fi
echo -e "$liste"
#dossier temporaires
rm .doesntExistinstalledPackages .doesntExistdatedPackages .doesntExistinstalledDatedPackages
if $verbose ;
then
echo "[Entrée]"
read
fi
Python
#!/bin/python
# adresse de base du fichier des logs.
log="/var/log/dpkg.log"
import subprocess
import os
import gzip
import re
os.chdir("/var/log/")
# thanks to http://forum.hardware.fr/hfr/Programmation/Python/python-suppresion-doublons-sujet_103862_1.htm
def nub1(inpt):
nv = []
[nv.append(item) for item in inpt if not item in nv]
return nv
class an_install:
def __init__(self, name, date, hour, version ):
self.name=name
self.date=date
self.hour=hour
self.version=version
self.cat=""
def __eq__(self,other):
return self.name.__eq__(other.name)
class dpkgFile:
def __init__(self, name):
self.name=name
def get_installs(self):
content=None
if "gz" in self.name:
content=gzip.open(self.name,"r")
else:
content=open(self.name,"r")
installs=[]
for line in content:
line_vals=str.split(line, " ")
operation=line_vals[2]
if not operation=="install":
continue
nameI=line_vals[3]
date=line_vals[0]
hour=line_vals[1]
version=line_vals[4]
installs.append(an_install(nameI, date, hour, version))
content.close()
return installs
tabListFichier=[]
# recuperation de tous les fichiers de log de dpkg :
listFichier = os.listdir(".")
for fichier in listFichier:
if "dpkg.log" in fichier:
tabListFichier.append(dpkgFile(fichier))
# tri des fichiers du plus recent au plus vieux.
tabListFichier.sort(key=lambda f: f.name)
# construction de la liste des installations
installs=[]
for dpkgF in tabListFichier:
installs.extend(dpkgF.get_installs())
installs.sort(key=lambda f:f.date)
date=installs[0].date
installs2=[]
for install in installs:
if install.date != date:
installs2.append(install)
installs=installs2
for install in installs:
if install.date == date:
print "echec"
# recuperation de la derniere installation uniquement
installs=nub1(installs)
proc = subprocess.Popen(["apt-mark","showmanual"], stdout=subprocess.PIPE)
manualInstalls,err = proc.communicate()
manualInstallsList=[]
for manualInstall in str.split(manualInstalls,'\n'):
if manualInstall != "":
manualInstallsList.append(manualInstall)
installs2=[]
for install in installs:
if install.name in manualInstallsList:
installs2.append(install)
installs=installs2
section=re.compile("Section: ([^\n/]*)")
for install in installs:
proc = subprocess.Popen(["apt-cache","show",install.name], stdout=subprocess.PIPE)
res,err = proc.communicate()
cat=section.search(res)
if cat is not None:
install.cat = cat.group(1)
installs.sort(key=lambda f: f.cat)
for install in installs:
print install.cat+" "+install.name+" "+install.date+" "
Je ferais évoluer la version python pour une meilleur détection des paquets installés lors de l'installation de Ubuntu, pour supprimer les paquets "linux", et d'autres fonctionnalités !
N'hésitez pas a me donner des conseils sur la version python !
PS : j'ai enfin pu supprimer la dépendance à aptitude 😉