Archives par mot-clé : Bash

Répéter un caractère sur toute la largeur du terminal

Un terminal comme Konsole ou Gnome Terminal est une fenêtre redimensionnable. Si l’on souhaite afficher une ligne de séparation sur toute la largeur de celui-ci, il est nécessaire de connaître le nombre de colonnes (ou de caractères) qu’il affiche, forcément variable. Une manière de connaître les dimensions du terminal consiste à lancer la commande stty : celle-ci affiche alors un nombre important d’informations, dont le nombre de colonnes du terminal en cours. Une autre manière de récupérer le nombre de colonnes, consiste plus simplement à lancer la commande tput avec pour argument « cols », dont voici un exemple :

[benoit:~]$ tput cols
237

En encapsulant, en Bash, la commande tput dans $(…), lors de l’exécution cette pseudo-variable sera automatiquement remplacée par sa valeur, 237 dans notre exemple. Voyons maintenant comment nous en servir avec printf pour écrire 237 caractères.

Sans entrer dans les détails de la commande printf, le fait d’écrire printf "%237s" " " permet d’afficher 237 espaces. Puisque notre terminal ne fera pas toujours 237 caractères de large, remplaçons cette valeur par $(tput cols) comme expliqué au-dessus.

Puisque nous souhaitons afficher un élément de séparation dans notre terminal, la série d’espaces devra être remplacée par une série d’autre chose. L’utilisation du « _ » (underscore, souligné, ou «tiret du 8») permettra de simuler une ligne tirée de bout en bout, mais le caractère « * » (étoile ou astérisque), moyennant un « petit ajustement » (ou plutôt un échappement), aurait tout aussi bien fait l’affaire. La commande sed va nous servir à remplacer chacun des espaces par un underscore, via un pipe (le fameux « | ») en sortie du printf. La fonction « printline » ci-dessous prend en compte l’ensemble des points abordés, à savoir l’utilisation de tput, printf et sed.

function printline ()
{
    printf "%$(tput cols)s\n" "" | sed s/' '/"_"/g
}

Cet exemple est déjà un bon début. Maintenant, nous souhaiterions pouvoir afficher une ligne avec n’importe quel caractère, sans avoir à modifier à chaque fois notre script. Pour ce faire, nous allons donc prévoir une variable, laquelle reposera sur le premier argument passé au script. La variable $c à la place du underscore permet de remplacer chaque espace par le caractère (ou les caractères, mais dans ce cas il y aura autant de lignes que de caractères !) passé en argument. Une dernière petite astuce va nous permettre d’utiliser un underscore par défaut. L’écriture ${c:=_} s’explique ainsi : si ma variable $c ne retourne aucun caractère, alors utiliser « _ ». L’exemple ci-dessous reprend la fonction précédemment écrite avec ces quelques améliorations.

function printline ()
{
    c=$1
    printf "%$(tput cols)s" "" | sed s/' '/"${c:=_}"/g | cut -c1-$(tput cols)
}

Cette fonction permet d’obtenir ces différents résultats :

[benoit:~]$ printline
________________________________________________________________________

[benoit:~]$ printline *
************************************************************************

[benoit:~]$ printline Abc
AbcAbcAbcAbcAbcAbcAbcAbcAbcAbcAbcAbcAbcAbcAbcAbcAbcAbcAbcAbcAbcAbcAbcAbcAbcAb

Exemples d’utilisation de la commande printf

La commande printf est une des commandes les plus utilisées en shell. Elle permet de formater les données que l’on souhaite afficher dans le terminal. Il est ainsi facile d’organiser sous forme tabulaire des données chiffrées, ou bien afficher un simple mot, un simple texte.

Parfois, la lecture d’informations dans le terminal mériterait d’être améliorée, afin de faciliter le confort visuel ainsi que faire immédiatement ressortir une information essentielle lors d’un traitement quelconque. Lorsqu’on écrit un programme en Bash, on ne prend pas toujours le temps de peaufiner l’affichage… alors qu’un titre centré, un séparateur horizontal ou un message d’erreur en rouge seraient du plus bel effet ! :mrgreen:

Les exemples qui vont suivre sont des cas relativement simples qui peuvent être implémentés et améliorés à loisir. Un premier intérêt ici est de découvrir les petites astuces, comme par exemple connaître la largeur du terminal, afin d’adapter l’affichage à ses besoins. L’autre intérêt, consiste à créer de petites fonctions réutilisables un peu partout dans ses scripts, et qui peuvent en outre être assemblées entre elles.

Pour chacun de ces cas, un premier exemple simplifié, permettant d’aller à l’essentiel, sera suivi d’un exemple un peu plus complet répondant à une problématique approfondie.

Bien entendu, ces exemples s’adressent aux personnes déjà familières de la ligne de commande. Dans le cas contraire, vous devriez peut-être vous armer d’une boîte de comprimés contre le mal de tête… ou ne pas lire, tout simplement… 😀

Pour découvrir (ou re-découvrir) ces différents cas, veuillez vous rendre sur les articles ci-dessous :

Creative Commons License
Publié sous licence Creative Commons.

Le dernier jour du mois ?

Dans la catégorie « astuces pour amoureux de la ligne de commande sous GNU/Linux », voici une petite commande qui peut s’avérer pratique dans le cas de certains développements en Bash. La simplicité de ce code n’a d’égal que sa beauté ! Bien entendu, cette remarque hautement poétique reste subjective… :mrgreen:

Pour une raison ou pour une autre, on peut avoir besoin de vérifier si la date du jour est le dernier jour du mois. Sauf que le dernier jour du mois peut être un 28, un 29, un 30 ou un 31.

La commande date du projet GNU permet de retourner une date autre que celle du jour. Il suffit alors de vérifier si « demain » sera le premier jour du mois suivant, et d’exécuter la commande de son choix en conséquence.

test `date +'%d' -d '1 day'` = "1" && echo "hello" || echo "world"

La ligne ci-dessus exécute la commande date en ajoutant « 1 jour » à la date actuelle. Le « %d » permet de récupérer le numéro du jour dans le mois. Si le test confirme que demain nous serons le 1er, alors le terminal affiche « hello » ; dans le cas contraire, le terminal affiche « world ».

Une manière plus académique d’écrire ce code au sein d’un script Bash, pourrait être l’exemple ci-dessous qui donnera le même résultat.

demain=`date +'%d' -d '1 day'`

if test "$demain" = "1"
then
	echo "hello"
else
	echo "world"
fi