Optimisation d'un script bash
Au cours d'une ènième discussion constructive avec Frank, on en est venu à parler, en autre, des scripts que l'on peut faire en bash. De fils en aiguilles, le sujet d'un script bash écrit pour optimiser les images du site est arrivé dans la conversation.
En 2017, je vous parlais de Guetzli, une librairie proposée par Google qui permet d'encoder les images au format JPG. Cela prend un peu de ressource pour l'encodage, mais au final, cela permet de limiter le poids, et donc la bande passante, pour un décodage pas beaucoup plus gourmand.
Pour les besoins du site, et éviter de lancer la commande pour chacune des images, je m'étais fait un petit script permettant de lancer la commande pour toutes les images d'un article.
Il suffisait de se placer dans le dossier source des images, et de lancer le script. Automatiquement, le script créé un dossier Opti à côté du dossier source, et lance Guetzli pour toutes les images, conservant le même nom, mais placées dans le dossier Opti.
Voici le script
#!/bin/bash
# create optimised picture folder
mkdir -p ../Opti
# read all files
for f in ./*; do
if [ ! -f $f ]; then
continue
fi
FULL_FILENAME=$f
FILENAME=${FULL_FILENAME##*/}
exec guetzli $f ../Opti/${FILENAME%%.*}.jpg &
done
Pas super compliqué, ce dernier commence par créer le dossier à côté, s'il n'existe pas. Ensuite, il fait une boucle sur tous les éléments du dossier, et s'il s'agit d'un fichier, il lance une commande Guetzli.
Comme les encodages étaient lancés en fond de tâche, il encodait plusieurs images à la fois, mais pas forcément de manière optimale.
Basiquement, cela fonctionne ! Je m'en servais à chaque article, jusqu'à maintenant.
Voici la nouvelle version, travaillée avec Frank
#!/bin/bash
# create optimised picture folder
mkdir -p ../Opti
# encode all jpeg pictures
find . -type f -name "*.jpg" | xargs -n1 -P8 -I {} guetzli {} ../Opti/{}
2 lignes, oui, 2 lignes et 2 commandes pour réaliser une action équivalente, encore plus évoluée. Mais cela nécessite quelques explications, non ?
La première commande est identique, et permet simplement de créer le dossier de sortie.
La commande se sépare en 2 parties, séparé par le caractère pipe, que l'on obtient, pour rappel avec Alt + Maj + L.
La partie, basée sur find, permet de récupérer la liste des fichiers JPG qui se trouvent dans le dossier.
Le pipe indique que l'on envoie le résultat dans la commande qui suit.
Ici, il s'agit de la commande xargs, qui débute la seconde partie de la commande.
Cette seconde partie peut aussi être découpée en deux pour plus de facilité de lecture et de compréhension.
D'un côté
xargs -n1 -P8 -I {}
La commande xargs représente toute la puissance de cette version du script. Il va prendre tous les résultats de la commande précédente pour les distribuer à la commande suivante.
Le paramètre -n1, indique que xargs va envoyer les paramètres 1 par 1.
Le paramètre -P8 indique qu'il doit limiter à 8 processus en simultané. C'est l'option ultime pour optimiser l'utilisation de votre ou vos CPUs. Au lieu de lancer tous les encodages en même temps saturant complètement la machine, xargs va distribuer les processus selon vos souhaits. Ainsi, si vôtre Mac peut gérer 6 threads, par exemple, je vous conseille de mettre le paramètre -P6 (ou -P5 si vous souhaitez conserver un coeur de libre, pour d'autres activités).
Enfin, le paramètre -I {} indique la chaîne de caractères qui serait remplacé par les résultats distribués par xargs.
Et de l'autre
guetzli {} ../Opti/{}
Il s'agit tout simplement, de la commande qui va encoder les images. Prenant en 1er paramètre le fichier à encoder, et en second, le fichier en sortie, composée du dossier qu'on avait prévu, et en conservant le même nom.
Magique, non ?