Embarquer une image dans un script bash
Quand je programmais en perl, une fonctionnalité de ce langage me plaisait beaucoup. Il est en effet possible d'embarquer des données dans un script après le mot clef __END__. Ces données sont alors facilement accessible dans celui-ci à l'aide du descripteur <main::DATA> Cela donne quelque chose comme cela :
#!/usr/bin/perl while (<main::DATA>) { print $_; } __END__ 1ère ligne 2ème ligne
Il m'est venu l'envie d'avoir la même chose en bash pour pouvoir embarquer une image à modifier dans un script[1]. Si bash ne propose pas une telle fonction par défaut, il est très facile de l'émuler avec les outils standard d'unix. Sans plus attendre, voila ce que ça donne :
#!/bin/bash END_LINE=$( awk '/^__END__/{print NR + 1}' $0) tail -n +$END_LINE $0 | base64 -di | display exit 0 __END__ iVBORw0KGgoAAAANSUhEUgAAAQgAAADAAQMAAADC9G/RAAAABlBMVEX///8AAABVwtN+AAAAVUlE QVRYhe3TwQ2AQAhFQfpvGhNNDCxSgfNu+5nrRtxlZvTOhSCIZfo4EwRRphlBEFO873priCCIjLpu EQRRxfZrnp0giCmiRxDEFHWqvytmBPF3cQGgZ+PFvE0lDQAAAABJRU5ErkJggg==
Les explications : grâce à awk, on récupère le numéro de ligne suivant le patern __END__. Puis tail nous permet de récupérer les données à partir de cette ligne que l'on passe à base64 en mode décodage. L'image ainsi obtenue est envoyée simplement à display[2]. Libre à vous d'en faire ce que vous voulez.On n'oubliera pas le exit avant les données, sinon bash va essayer de les interpréter comme du code.
Pour intégrer l'image, on utilisera par exemple :
$> base64 si.png >> img.sh
On peut aussi pour gagner de la place garder l'image en binaire (et éviter ainsi l'encodage/décodage base64) mais comme certains éditeurs ont parfois du mal avec les fichiers contenants du binaire, je préfère le base64. Il est facile de remplacer l'image par n'importe quoi, comme par exemple un tgz pour faire un script auto-extractible.
Voila une astuce simple mais diablement utile !