mercredi 10 décembre 2014

variables Bash : bye bye basename

édition rapide du contenu des variables sous bash et dash

Bash a un mécanisme d'édition de variables intégré permettant d'en supprimer le début ou la fin. En prime, ça peut aussi compter la longueur du contenu.

Pour supprimer le début c'est avec #. Si on prononce # « dièse », ça commence par un D comme « début ».

Pour supprimer la fin c'est avec %. Bon, on peut se dire qu'un pourcentage s'écrit avec % à la fin pour s'en souvenir.

Exemples d'utilisation

transformer un flac en ogg
sox $chanson ${chanson%.flac}.ogg
calculer la longueur d'un mot
echo $mot fait ${#mot} char. de long
afficher le début d'un texte
echo début du texte : ${texte:0:30}
évaluer le chemin du script exécuté
chemin=${0%/*}
évaluer le chemin du script exécuté, complété pour le cas des liens symboliques
this=$(readlink -e $0)
chemin=${this%/*}
afficher le seul nom du script exécuté
echo ${0##*/}
supprimer un éventuel / final à un nom de répertoire
repertoire=${repertoire%/}

Tout cela fonctionne aussi avec dash !

Une petite colle maintenant : si votre script est appelé par la commande point (.) alors $0 n'est pas le nom de votre script mais celui du shell appelant ou du script appelant. Comment récupérer le nom du script dans ce cas-là ? Je n'en sais rien !

un petit exemple concret

Le programme suivant permet d'éditer en mode comparaison tous les couples de fichiers de même nom dans deux répertoires différents, en se restreignant au seul cas où ils ont un contenu différent. C'est un script dash pour plus de radipité au lancement. L'éditeur utilisé est vim ou gvim (sous la forme vimdiff ou gvimdiff).

#!/bin/sh

# édite les fichiers de même nom dans deux répertoires mais différents

usage() {
  echo "usage: ${0##*/} [-g] dir01 dir02"
  echo "Edit same files in both directories with different contents only."
  echo "With -g use gvimdiff instead of vimdiff."
  exit 1
}

editor=vimdiff
if [ "$1" = '-g' ] ; then
  editor=gvimdiff
  shift
fi
[ $# -eq 2 ] || usage
dir01="${1%/}"
dir02="${2%/}"
ndiff=0
ntotal=0

compare() {
  if [ -f $2 ] ; then
    ntotal=$((ntotal+1))
    if ! cmp --quiet $1 $2 ; then
      #echo '!=' DIFF $1 $2
      $editor $1 $2
      ndiff=$((ndiff+1))
    fi
  fi
}

files=$(find "$dir01" -maxdepth 1 -type f)
for f01 in $files ; do
  f02=$dir02/${f01##*/}
  compare $f01 $f02
done
echo "$ndiff couples of files were different out of $ntotal."