Les bases du bashAuteur : Julien Gauchet le 29/11/2017 (2 revisions)

Cette page présente le fonctionnement de l'interpréteur bash ainsi que la syntaxe des commandes qu'il utilise

1. La grammaire du shell

Pour être en mesure d'exécuter des commandes, le bash ou le kornshell exigent une structure particulière de la commande. Une ligne de commande est réalisée à l'aide d'une commande simple ou bien en combinant des commandes simples à l'aide d'opérateurs décrits ci-dessous.

1.1. Les commandes

Une commande est associée à

  • Des options : elles modifient le comportement de la commande
  • Des arguments : qui sont des paramètres sur lesquels la commande va travailler
Les options sont précédées de "-" alors que les arguments ne le sont pas.

Le format d’une commande simple est donc le suivant :

Format d'une commande

La commande la plus simple est la commande echo qui permet d’afficher un texte dans la console. Cette commande prend un argument : le texte à afficher :

echo 'le texte à afficher'
le texte à afficher

1.2. Les variables

Les variables permettent de stocker des valeurs. Le script suivant illustre la création et l'utilisation d'une variable.

variable=valeur
echo $variable
valeur

1.3. Les scripts

Les scripts ksh sont des suites d’instructions enregistrées dans des fichiers et qui sont exécutées lorsque le fichier est appelé dans une invite de commandes :

/home/user/script.ksh

On peut passer un argument à un script en l’écrivant après l’appel, les arguments sont séparés par des espaces :

/home/user/script.ksh argument1 argument2

Pour accéder à l’argument n dans le script, on utilise la variable $n. La variable $* contient l’ensemble des arguments.

1.4. Les fonctions

Une fonction permet de regrouper un ensemble de commandes dans un script par exemple. Pour créer une fonction, on utilise la syntaxe suivante :

function exemple 
{
	instruction1
	instruction2
}

Les fonctions sont utilisées comme les commandes. On peut comme pour les scripts utiliser des arguments.

1.5. Les alias

Un alias permet de substituer une chaine de caractères à un mot. Par exemple, si on fait de nombreux appels à un script : /dev/fs/C/Users/user/Desktop/script.ksh, on peut faire un alias sur ce script :

alias script=/dev/fs/C/Users/user/Desktop/script.ksh

De cette manière, les appels au script se feront en utilisant la commade script.

2. Les sctructures

2.1. Les structures de contrôle conditionnelles

On appelle structure conditionnelle les instructions qui permettent de tester si une condition est vraie et de déclencher des traitements en fonction de la valeur de cette condition.

La syntaxe de la structure est la suivante :

if [condition]
then 
	[liste de commandes]
elif [condition]
then
	[liste de commandes]
else
	[liste de commandes]
fi
Remarque : dans le cas où nous n’avons que des instructions dans le bloc if, on peut utiliser la syntaxe suivante :
[[ [condition] ]] && [liste de commandes]

Cette forme est plus simple à écrire et est interprétée plus rapidement mais elle est moins lisible, elle sera préférée dans le cas où une seule opération sera effectuée si la condition est vraie et si aucune opération est effectuée si la condition est fausse.

2.1.1 Les conditions

Pour évaluer les conditions, le bash utlise les codes retour des commandes. Si le code retour est 0 alors la condition est vrai et la condition est fausse sinon. Toutes les commandes peuvent donc être passées en paramètre d’un if.

Il existe une commande particulière « test ».qui permet d’évaluer une expression booléenne, cette commande fonctionne de la manière suivante :

test 2 -eq 2
echo $?
0

2 est bien égal à 2, $? est donc égal à 0.

test 2 -eq 4
echo $?
1

Dans ce cas, $? est égal à 1

Dans la pratique, nous n'utiliserons pas la commande test mais un alias : [[ 2 -eq 4 ]]. O écrira alors

[[ -e /fichier ]] && echo le fichier existe
[[ 2 -gt 1 ]] && echo vrai
vrai

La commande test connaît les opérateurs suivants :

  • -eq : égal
  • -ne : différent de
  • -gt : plus grand que
  • -lt : inférieur à
  • -ge : supérieur ou égal
  • -le : inférieur ou égal
  • -e : existe (pour un fichier)
  • -d : est un dossier
  • == : deux chaines sont identiques
  • != : deux chaines sont différentes

2.1.2 Les calculs

Pour évaluer une expression numérique, on peut utiliser la commande expr. Par exemple

[[ $(expr 2 + 2) -eq 4 ]] && echo ok
ok

Cette commande possède un alias particulier : (( )). La ligne précédente est donc équivalente à :

(( 2 + 2 == 4 )) && echo ok
ok

2.2. La boucle switch

Lorsqu'on veut effectuer différentes opérations selon la valeur d'une variable, l'instruction if peut devenir très lourde à utiliser. En effet, si le nombre de valeurs différentes est grand, elle peut conduire à écrire un grand nombre de tests.

Le shell fournit donc une instruction de branchement conditionnel, qui permet de spécifier quelle action doit être prise pour chaque valeur de la variable.

Cette boucle permet d’effectuer un traitement selon la valeur d’une variable. On peut utiliser un caractère générique : * qui signifie pour toutes les autres valeurs de la variable

La syntaxe de la structure est la suivante :

case $variable in
	choix1 )
		[commandes];;
	choix2 )
		[commandes];;
	* )
		[commandes];;
esac

Remarque : l’utilisation de cette boucle peut être utile quand la variable peut prendre un grand nombre de valeurs, dans le cas contraire, on utilisera plutôt la boucle if.

2.3. La boucle for

Cette boucle permet de répéter un traitement plusieurs fois en fonction des valeurs que nous passons en argument de la commande.

La boucle for du bash est différente de la boucle for dans d’autres langages de programmation, en effet, elle ne permet pas d’itérer sur la valeur d’une variable mais elle effectue un traitement sur un ensemble de valeurs passées en paramètre et séparées par des espaces.

La syntaxe de la structure est la suivante :

for var in [liste]
do
	[liste_commandes]
done

Remarque : l’utilisation de cette boucle peut être utile quand la variable peut prendre un grand nombre de valeurs, dans le cas contraire, on utilisera plutôt la boucle if.

2.4. La boucle while

La boucle while permet de répéter une suite d’instructions tant qu’une condition est vraie.

C'est cette boucle qu'on utlisera pour itérer sur une valeur. Il faudra l'incrémenter à chaque itération pour qu'elle ait un comportement similaire à celui d'une boucle for traditionnelle dans d'autres langages de programmation.

La syntaxe de la structure est la suivante :

while [condition]
do
	[liste_commandes]
done

Remarque : on utilise parfois à tort une boucle while à la place d'une boucle for. La boucle for est plus rapide à exécuter que la boucle while.

Les conditions fonctionnent de la même manière que pour la boucle Si.

Pour utiliser l'équivalent d'une boucle for :

i=0
while [[ $i -lt 10 ]]
do
	echo $i
	(( i++ ))
done

Dans ce cas, on peut également utiliser une boucle for de la manière suivante :

for var in 0 1 2 3 4 5 6 7 8 9
do
	echo $i
done

Mais ceci n'est possible que si la bone supérieure est fixe.

3. Les entrées et les sorties

3.1. Présentation

Un processus (une commande ou un script) est associé à :

  • L'entrée standard qui est le flux d'entrée par lequel du texte ou toute autre donnée peut être entrée dans un programme. Par défaut, le clavier.
  • La sortie standard (stdout) qui est le flux de sortie dans lequel les données sont écrites par le programme. Par défaut, la console.
  • L'erreur standard (stderr) qui est le flux de sortie permettant aux programmes d'émettre des messages d'erreurs et des diagnostics. Par défaut, la console.
Entrées et sorties d'un processus

3.2. Redirections

Il est possible de rediriger les entrées sorties d’une commande ou d’un script vers un autre fichier :

3.2.1 Redirection de l'entrée

Pour rediriger l'entrée, on utilise le caractère < de cette manière

commande < /fichier.txt

Par exemple :

tr 'A' 'Z' < /dev/fichier.txt

3.2.2 Redirection des sorties

Pour rediriger la sortie standard vers un fichier, on utilise le caractère > de la manière suivante :

commande > /fichier.txt

Pour ajouter des lignes au fichier vers lequel on redirige, on utilise >>. La ligne suivante ajoute "abc" à la fin du fichier /fichier.txt :

echo abc >> /fichier.txt 

Pour rediriger l'erreur standard, on utilise les caractères 2> de la manière suivante :

commande 2> /fichierErreur.txt

Par exemple :

./script.ksh > /dev/fichier.txt 2> /dev/erreur.txt

De la même manière, on peut ajouter des lignes au fichier en utilisant 2>>.Il est possible de "brancher" la sortie en erreur sur la sortie standard comme ceci : 2>&1. Par exemple :

./script > /dev/fichier.txt 2>&1 
Redirection des sorties d'un processus

3.3. Les pipes

Les redirections nous permettent de rediriger les entrées et les sorties d'une commande vers un fichier texte. Il est également possible de relier les entrées d'une commande vers la sortie d'une autre

Redirections entre processus

Ceci se réalise avec l'opérateur | de cette manière :

echo AZERTY | tr 'A' 'Z'
ZZERTY

On peut également réaliser un pipe en incluant l'erreur standard

Pipes incluant l'erreur standard
./script.ksh 2>&1 | tr 'A' 'Z'

4. Lecture d'une ligne de commande

4.1. Principe

Pour effectuer les opérations décrites dans le programme, le bash traite la ligne de commande qui est entrée et la transforme en instructions système. Afin de séparer et repérer les différentes composantes d'une commande, le shell va se baser sur des opérateurs (&& par exemple) et séparateurs (espace, > par exemple). La partie suivante décrit l'ordre d'exécution de chacune des étapes amenant à exécuter une commande

4.2. Les étapes

4.2.1 Découpage de la ligne en mots et opérateurs

Le shell recherche les meta-caractères non protégés : |, >, && et la ligne est découpée en mots en fonction de ces caractères. Pour protéger un caractère, on utilise le \ ou on place ce caractère entre quotes simples ou doubles.

4.2.2 Traitement des alias

Un alias permet de substituer une chaine de caractères à un mot lorsqu'il est utilisé comme le premier mot d'une commande simple. Le traitement des alias signifie effectuer cette substitution

4.2.3 Analyse du résultat obtenu en terme de commande simple ou composée

L'analyse du résultat obtenu après le traitement des alias permet de déterminer si la commande est simple (ls /dev) ou composée (ls $(cat /home/fichier.txt)).

Dans le cas d'une commande composée, il faudra d'abord exécuter certains blocs de code avant d'en exécuter d'autres.

4.2.4 Développement du ~

Le ~ représente le répertoire de connexion de l'utilisateur.

4.2.5 Expansion des paramètres et variables

Les paramètres ($1, $2) et les variables ($var) sont remplacés par leurs valeurs. Remarque : cette opération est effectuée après le traitement des alias, si une variable contient un alias, celui-ci ne sera pas traité comme tel.

4.2.6 Évaluation des commandes internes

L'écriture $(commande) o u `commande` représente une évaluation de commande. Elle permet de remplacer une commande par son résultat.

4.2.7 Expansion des expressions arithmétiques

Les expressions arithmétiques sont ensuite évaluées. Une expression arithmétique est un calcul effectué de la manière suivante : (( $compteur + 1 ))

4.2.8 Découpage en mots de la ligne obtenue

La ligne est formatée, tous les mots sont alors séparés par un seul espace. La commande est alors une commande simple.

4.2.9 Développement des noms de fichiers

Les noms de fichier relatifs ./fichiers sont remplacés, les caractères * est également résolu.

4.2.10 Mise en place des redirections

Les redirections sont créées.

4.2.11 Suppression des protections

Toutes les occurrences non protégées de \ ‘' ou ‘ sont supprimées

4.2.12 Localisation et exécution de la commande

La commande est recherchée dans les fonctions, dans le path et exécutée. Le graphique ci-dessous illustre la localisation et l'exécution d'une commande par le shell.

Localisation d'une commande