cClaude.rocks ☕ Le blog

[Nouvelles technologies du libre, sciences et coups de gueule…]

Menu

Ce billet se propose, sur la base d'une curiosité, d’explorer quelques fonctionnalités autour bash et des commandes apt, diff, sed et sort.



Présentation

Dans un précédent billet 📦 Lister et enregistrer les paquets installés sur votre Linux, j’affirmais que :

dpkg --get-selections
apt list --installed

… donnaient la même information.

Eh bien, il est possible de le vérifier avec la commande suivante :

diff --side-by-side --suppress-common-lines <( dpkg 2>/dev/null --get-selections | sed -E 's,^([^[:blank:]:]+).*,\1,g' | sort ) <( apt 2>/dev/null list --installed | sed -E 's,^([^/]*)/.*,\1,g' | sort )

Mais c’est pas forcément très clair, n’est-ce pas ?

On peut reformater comme cela :

diff --side-by-side --suppress-common-lines <(
  dpkg 2>/dev/null --get-selections |
    sed -E 's,^([^[:blank:]:]+).*,\1,g' |
    sort
  ) <(
  apt 2>/dev/null list --installed |
    sed -E 's,^([^/]*)/.*,\1,g' |
    sort
  )

L’affichage attendu est « presque » vide (ce qui est attendu du fait du drapeau --suppress-common-lines), je propose de regarder le résultat sur votre Linux la ligne suivante :

diff --side-by-side  <( dpkg 2>/dev/null --get-selections | sed -E 's,^([^[:blank:]:]+).*,\1,g' | sort ) <( apt 2>/dev/null list --installed | sed -E 's,^([^/]*)/.*,\1,g' | sort )


Décortiquons

La ligne initiale peut se décomposer ainsi :

  • La commande diff :
diff --side-by-side --suppress-common-lines XXX0 YYY0

Enfin, plus précisément ainsi, mais nous verrons plus en détail ce que cela veut dire un peu plus loin :

diff --side-by-side --suppress-common-lines <( XXX1 ) <( YYY1 )

Avec les deux commandes suivantes :

  • La commande dpkg et le reformatage de sa sortie :
dpkg 2>/dev/null --get-selections | sed -E 's,^([^[:blank:]:]+).*,\1,g' | sort
  • La commande apt et le reformatage de sa sortie :
apt 2>/dev/null list --installed | sed -E 's,^([^/]*)/.*,\1,g' | sort

La commande « diff »

La commande diff permet de comparer les fichiers ligne à ligne.

La syntaxe de base est :

diff FICHIER1.txt FICHIER2.txt
  • Le drappeau -y ou --side-by-side affiche le résultat de la commande sur deux colonnes.
  • Le drappeau --suppress-common-lines demande à ne pas afficher les lignes communes.

On note que la commande diff attend deux fichiers textes dans sa ligne de commande. Laissons ce problème de côté pour le momment.

Ceci correspond à cette version de la ligne de commande :

diff --side-by-side --suppress-common-lines XXX0 YYY0

La commande « apt » et le reformatage de sa sortie :

La commande apt est un système de gestion de paquets logiciels. Pour la gestion au quotidien des paquets.

apt 2>/dev/null list --installed | sed -E 's,^([^/]*)/.*,\1,g' | sort

Que l’on va décomposer ainsi :

  • apt list --installed — pour commencer
  • apt 2>/dev/null list --installed — ensuite

puis :

  • sed -E 's,^([^/]*)/.*,\1,g'
  • sort
  • Le selecteur list est quelque peu similaire à dpkg-query --list dans le sens où il peut afficher une liste de paquets répondant à certains critères. Il prend en charge l'options permettant de lister les versions installées (--installed).

Ce qui correspond précisément à notre cas d'usage.

Cependant, la documentation de la commande apt alerte sur son utilisation dans le script (ce qui nous le verrons puis loin est le cas ici).

La ligne de commande apt(8) est conçue comme un outil pour l'utilisateur final et son comportement peut changer entre les versions. Bien qu'elle essaie de ne pas rompre la compatibilité ascendante, cela n'est pas non plus garanti si un changement semble bénéfique pour une utilisation interactive.

Le pipeline | qui suit la commande et permet de prendre le résultat de la commande apt pour retraiter par la suite fait que de fait, la commande apt est utilisée dans script. Cela est détecté par la commande apt qui affiche une alerte sur la sortie d'erreur (stderr). Pour éviter cet affichage on utilise la redirection de la sortie d'erreur (2>) vers un fichier qui absorbe tout ce qu'on lui envoie : /dev/null.

La commande complète apt 2>/dev/null list --installed n’affichera donc pas les erreurs, ni le message d’alerte.

Le résultat sera envoyer vers la commande sed :

  • sed -E 's,^([^/]*)/.*,\1,g' permet de n’afficher que ce qui est devant le caractère /, le reste de chaque ligne sera ignoré. La commande sed est un éditeur de ligne, le traitement se fait donc ligne par ligne.

  • sort permet de trier les lignes ainsi générées.


La commande « dpkg » et le reformatage de sa sortie :

La commande dpkg est le gestionnaire de paquets pour Debian.

Le drapeau --get-selections permet d’obtenir la liste des sélections des paquets, et l’envoie sur la sortie standard.

dpkg 2>/dev/null --get-selections | sed -E 's,^([^[:blank:]:]+).*,\1,g' | sort

On applique les mêmes principes que pour apt, sauf que l’expression régulière est différente.

On verra en annexe, ce le détail des deux expressions réguliers utilisées.


Remettons tous cela ensemble grâce à <( … )

Basiquement, on pourrait faire comme suit :

dpkg 2>/dev/null --get-selections | sed -E 's,^([^[:blank:]:]+).*,\1,g' | sort >XXX0
apt  2>/dev/null list --installed | sed -E 's,^([^/]*)/.*,\1,g'         | sort >YYY0

diff --side-by-side --suppress-common-lines XXX0 YYY0

Les deux premières lignes effectuant les traitements expliqués et mettant chacun des résultats dans un fichier. Il suffit alors d’utiliser diff en précisant le nom des fichiers créés préalablement.

Cependant, cette solution implique de gérer des fichiers temporaires: s'assurer de ne pas écraser un fichier existant et supprimer les fichiers en fin de traitement.

C’est là que la notation <( … ) intervient, puisque c’est exactement ce qu’elle fait. Il n’y a alors plus besoin d'utiliser 3 étapes, on peut tout faire dans une même suite de commandes.



Liens

ᦿ


ℹ 2006 - 2024 | 🏠 Accueil du domaine | 🏡 Accueil du blog