Généralités
Commencer par indiquer l’utilisation de bash pour l’exécution de votre script en haut du fichier grâce au « shebang » :
#!/bin/bash
Inclure un fichier dans un script :
. cheminfichier
Les variables
Généralités
Déclaration d’une variable nommé mavariable : mavariable= »mon.fichier.sql » echo $mavariable donne mon.fichier.sql pour éviter des erreurs dans les substitutions de variable, il est bon d’utiliser echo ${mavariable}
Sans précision, une variable déclarée dans le script est disponible dans tout ce script, y compris les fonctions.
Attention, elle n’est pas accessible à un sous processus.
Il est possible de préciser devant la variable le terme local par exemple dans une fonction afin que cette variable ne soit valable qu’à l’intérieur de la fonction et sous fonctions.
Nombre de caractères de la variable (longueur de la chaîne) :
${#mavariable}
Affecter une valeur par défaut à une variable nulle ou inexistante :
${mavariable:-defaut}
Dans ce cas, la variable n’est pas modifiée. Pour que la valeur soit affectée à la variable, il faut utiliser :
${mavariable:=defaut}
Attention, il ne faut pas appeler directement ${mavariable:=defaut} sans commande sinon bash effectuera l’affectation si nécessaire mais retrouvera une erreur :
${mavariable:=defaut} bash: defaut: command not found
Il est possible pour contourner cette erreur d’effectuer :
echo ${mavariable:=defaut} > /dev/null
Mais cela n’est pas très propre, il vaut mieux d’utiliser la commande : de bash lui indiquant d’ignorer l’opération et appeler ainsi :
: ${mavariable:=defaut}
Il est possible de tester si une variable est définie et non vide :
: ${mavariable:?non définie}
Dans le cas où la variable n’est pas définie ou est nulle, bash terminera l’exécution et affichera le message après le ?
Sous-chaînes
${mavariable:debut:longueur} permet d’extraire un certain nombre de caractère d’une chaîne :
${mavariable:2:4} renvoie : n.fi ${mavariable:2} renvoie : n.fichier.sql
Suppression du plus court préfixe correspondant au motif indiqué après le caractère # :
${mavariable#mon.} renvoie : fichier.sql
Suppression du plus long préfixe correspondant au motif indiqué après les caractères ## :
${mavariable##*i} renvoie : er.sql
Suppression du plus court suffixe correspondant au motif indiqué après le caractère % :
${mavariable%.sql} renvoie : mon.fichier
Suppression du plus long suffixe correspondant au motif indiqué après les caractères %% :
${mavariable%%i*} renvoie : mon.f
Environnement et attributs de variable
De base, les variables ne sont pas transmises entre les processus, par exemple lors du lancement d’un script depuis un autre.
S’il est nécessaire de transmettre une variable, il faut la mettre dans l’environnement grâce à la commande export :
export variable
Attention, la variable est « copie » dans le nouveau shell. Si une modification est apportée dans le nouveau shell, elle ne sera pas répercutée dans le shell parent.
Il est possible d’exporter plusieurs variable à la fois :
export variable1 variable 2
La commande declare parmet aussi avec l’option -x d’exporter dans l’environnement la variable :
declare -x variable
On le voit lorsque l’on liste les variables exportées avec :
export -p
Pour annuler l’export :
export -n variable
Un autre attribut intéressant à une variable est d’empêcher la modification :
declare -r variable
variable est alors en lecture seule. Attention, cet attribut n’est pas exporté dans l’environnement d’un nouveau shell.
Variables prédéfinies
- PID du processus :
$$
- PID du processus parent :
$PPID
- PID de la dernière commande lancée en arrière plan :
$!
- Répertoire personne :
$HOME
- Répertoire courant :
$PWD
- Répertoire précédent :
$OLDPWD
Les tableaux
La déclaration d’un tableau n’est pas obligatoire mais il est possible de le faire ainsi :
declare -a tableau
Pour affecter une valeur à un tableau :
tableau[0]=valeur tableau[1]=valeur2
Pour consulter la valeur des éléments d’un tableau :
${tableau[1]}
Nombre d’éléments dans un tableau :
${#tableau[@]}
Taille d’un élément :
${#tableau[1]}
Les arguments passés à un script ou à une fonction dans un script
Ils sont appelés variables de position.
L’argument null est définit par $0 qui représente le nom du script (tel qu’il a été exécuté).
Le nombre d’arguments passés en paramètre $# n’est pas limité à 9 contrairement à certaines affirmation.
De 1 à 9, il est possible d’utiliser l’appel de variable ainsi $1 à $9. Au dessus de 9, il suffit de bien délimiter le nom de la variable ainsi ${10}, ${11}, etc …
L’ensemble de la liste des arguments est : $*
Attention, il faut utiliser $* si vous êtes sûr que les arguments n’auront pas d’espaces sinon il est préférable d’utiliser $@ entouré de » ainsi :
#!/bin/bash # #Appel d'un sous script en passant les arguments ./sous-script.sh "$@"
L’identifiant du processus est $$
La commande set parmet de redéfinir l’ensemble des arguments à l’intérieur du script :
set 2 3 4 echo $1 $2 $3
-> 2 3 4 S’il y avait plus de trois paramètre avant la redéfinition des arguments avec set 2 3 4 alors ils seront effacés.
La commande shift permet de décaler l’ensemble des valeurs des paramètres (sauf $0) :
./script 1 2 3 shift echo $1 $2 $3
-> 2 3
Les options de lancement du script
Script d’exemple lisant les options passées au lancement du script
OPTIND=0 while getopts ":abc-:" opt ; do case $opt in a ) optiona=1 ;; b ) optionb=1 ;; c ) optionc=1 ;; - ) case $OPTARG in version ) echo "Version 1.0" exit 0;; * ) echo "option illégale -$OPTARG" exit 1;; esac ;; ?) echo "option illégale -$OPTARG" exit 1;; esac done shift $(($OPTIND - 1))
La fonction getopts renvoie vrai tant qu’il y a des options. En paramètre, nous lui fournissons la liste des options possibles puis le nom de la variable qui contiendra l’option.
Pour les options longues comme –version, il faut indiquer – suivi de : pour indiquer qu’il y aura des caractères après le tiret.
Le premier : sert pour stocker dans la variable OPTARG l’option illégale et mettre un ? dans la variable choisie pour les options (opt dans l’exemple).
Les options sont en réalité des arguments au script comme les autres.
getopts parcours les arguments pour en trouver commençant par un tiret et incrémente OPTIND.
Afin d’appeler les arguments qui ne sont pas des options à partir de l’indice 1, il faut décaler les arguments après traitement des options avec l’appel :
shift $(($OPTIND - 1))
Tests [ ]
Les tests sont réalisés avec la commande interne [ ].
Il doit toujours y avoir des espaces à l’intérieur de [ ] :
[ $i -lt 10 ]
A l’aide des opérateurs && (ET) et || (OU) il est possible d’utiliser les tests pour exécuter des commandes selon des conditions :
[ $i -lt 10 ]&& echo $i
[ -f $fichier ] || echo $fichier n'est pas un fichier
Paramètres pour les tests [ ]
Chaînes :
s1 # Vrai si la chaîne n'est pas vide s1 = s2 # Vrai si les chaînes sont identiques
Nombres :
n1 -eq n2 # Vrai si les 2 nombres sont identiques n1 -ne n2 # Vrai si les 2 nombres sont différents n1 -gt n2 # Vrai si n1 est plus grand que n2 n1 -ge n2 # Vrai si n1 est plus grand ou égal à n2 n1 -lt n2 # Vrai si n1 est plus petit que n2 n1 -le n2 # Vrai si n1 est plus petit ou égal à n2
Fichiers :
-d nomfichier # existe et est un dossier -e nomfichier # existe -f nomfichier # existe et est un fichier normal -r nomfichier # existe et est un lisible -w nomfichier # existe et est écrivable -x nomfichier # existe et est exécutable -s nomfichier # existe et est non vide
! condition # Retour l’opposé de la condition
Opérateurs dans les tests :
-a # AND ou ET -o # OR ou OU
Les structures de contrôle
- IF
if [ 1 ]; then echo "toto" else echo "titi" fi
if [ 1 ] then echo "toto" else echo "titi" fi
Il est possible d’ajouter un autre cas au if : elif [ condition ]; then
- CASE
case $variable in 1) echo "toto" ;; 2) echo "titi" ;; *) echo "defaut" esac
- FOR
for i in $* do echo $i done for i in `ls` do echo $i done
Attention si vous avez des espaces dans des fichiers que vous souhaitez garder, il faut changer la variable IFS :
OLDIFS=${IFS} IFS=$(echo -en "\n\b") for i in $(grep chaine *) do vos_commandes $i done IFS=${OLDIFS}
- WHILE
i=1 while [ $i -le 3 ] do echo $i i=`expr $i + 1` done
Calculs
La réalisation de calcul s’effectue par l’utilisation de l’opérateur $(( calculs )). Attention, les calculs ne sont possibles ainsi que sur des entiers, sinon, il faut utiliser la commande bc. Exemple pour la somme de deux variable a et b :
resultat=$(( $a + $b))
Appel à une commande
Dans un script, vous pouvez par exemple lancer une commande tar ou date directement comme :
date tar -zcf fichier.tar.gr dossier/
Parfois, il est nécessaire de mettre le résultat d’une commande dans une variable.
Il n’est pas possible d’écrire :
variable=date
Il s’agit là d’une affectation de la chaîne date à la variable nommée variable. Une écriture couramment employée est :
variable=`date`
Elle fonctionne mais n’est pas la syntaxe normale pour bash, il faut utiliser :
variable=$(date)
Il est parfois utile de préparer une expression à l’avance et de l’évaluer ensuite :
aevaluer="echo \$variable" eval $aevaluer
Les fonctions
Déclarer une fonction
function nomfonction(){ ... }
Appel de la fonction :
nomfonction parametre1 parametre2 ... parametre9
Export dans l’environnement :
export -f nomfonction
Redirection d’entrées/sorties
Les entrées et sorties standard par défaut sont :
- STDIN : entrée standard de numéro 0
- STDOUT : sortie standard de numéro 1
- STDERR : sortie standard des erreurs de numéro 2
0 ---> COMMANDE | ----> 1 | ----> 2
Les redirections sont effectuées avec les opérateurs >, >>, < et <<
- > redirige par défaut la sortie standard 1 vers un fichier
- >> redirige par défaut la sortie standard 1 vers un fichier en ajoutant à la fin du fichier.
- < redirige l’entrée standard 0 depuis un fichier
- << redirige l’entrée standard 0 depuis le texte suivant l’opérateur, un séparateur de fin est alors nécessaire.
Dans le cas de > et >>, il est possible de préciser le numéro de la sortie à rediriger : 2> ou 1>.
Si les deux sorties sont à rediriger, il est possible d’utiliser 2>&1 > /dev/null ou le raccourci &> /dev/null
Exemples pour > et >> :
echo texte > /home/utilisateur/fichier echo $(date) >> /home/utilisateur/fichier find . -name test.txt 2> /dev/null
Exemples pour < et << :
Contenu de mail.txt :
helo tortuegeniale.dj-j.net mail from: email@domaine.net rcpt to: destinataire@domaine.fr data Subject:Bonjour test .
Utilisation de < :
telnet localhost 25 < mail.txt
Même chose sans les affichages à l’ecran :
telnet localhost 25 < mail.txt &> /dev/null
Utilisation de << :
telnet localhost 25 << FIN helo tortuegeniale.dj-j.net mail from: email@domaine.net rcpt to: destinataire@domaine.fr data Subject:Bonjour test . FIN
Particularité :
L’utilisation de <<- permet de supprimer les tabulations (pas les espaces) :
telnet localhost 25 <<- FIN helo tortuegeniale.dj-j.net mail from: email@domaine.net rcpt to: destinataire@domaine.fr data Subject:Bonjour test . FIN
Fonctionnalités avancés de bash
- configuration du shell avec la commande set
Par exemple, il est possible de provoquer une erreur lors de la lecture d’une variable inexistante :
set -u
- désactivation d’une commande interne
Par exemple, la commande echo existe en interne à bash et en version système, pour désactiver la version bash :
enable -n echo
- utilisation d’une commande redéfinie par une fonction
Par exemple, vous redéfinissez la fonction echo mais vous souhaitez l’utiliser dans la nouvelle fonction, il faut alors utiliser builtin :
function echo() { builtin echo "Nouvelle fonction echo" builtin echo "$@" }
Astuces et commandes utiles
Changer la casse
minuscules=$(echo ${variable}|tr A-Z a-z)
La date
- Date courante en secondes depuis 1970…
date +"%s"
-> 1272622472
- Date courante selon un format :
date +"%Y%m%d-%H:%M:%S"
-> 20100430-12:14:03
- Conversion de date :
date -d'2010-04-30 11:34:16' +%s
-> 1272620056
Générer une suite de nombre
seq 10#renvoie 1 2 3 4 5 6 7 8 9 10 seq 10 15#renvoie 10 11 12 13 14 15
Quelques exemples
Générer un csv comparant des variables dans plusieurs fichiers de configuration.
#!/bin/bash DIFF=/tmp/diff.csv echo -n "var;">$DIFF for i in $(ls /tmp/pgconf_*) do echo -n ${i#/tmp/pgconf_}";" >> $DIFF done echo "" >> $DIFF for var in $(awk '{ print $1 }' /tmp/pgconf_mirakl1001) do echo -n $var";" >> $DIFF for i in $(ls /tmp/pgconf_*) do echo -n $(grep "^$var" $i|awk '{ print $3 }') >> $DIFF echo -n ";" >> $DIFF done echo "" >> $DIFF done