Bash (Une introduction)
Fichier script
Cette page traite des scripts shell. Elle a pour objectif de donner, de manière concise, des outils permettant de faire beaucoup de tâches courantes dans un environnement UNIX. Le seul prérequis est le stage UNIX de première année suivi d'une certaine pratique du shell, cette page s'adresse à des utilisateurs UNIX niveau débutant à intermédiaire.
Description
Un script shell est un ensemble de commandes shell rassemblées dans un fichier. L'extension de ce fichier est généralement en '.sh' . Les commandes peuvent se suivre comme si on les tapait successivement dans le terminal, il est également possible de faire des fonctions afin de rendre les scripts plus évolués. Les scripts shell sont souvent utilisés pour automatiser des manipulations sur des fichiers et dossiers : édition, suppression, modifications. On peut par exemple écrire des scripts qui génèrent des pages HTML de manière automatique.
En tête
Par convention (et je vous recommande très vivement de la respecter),
on définit le langage shell utilisé sur la première ligne du
script. Ainsi, un script en Bourne shell commencera par
#!/bin/sh. En pratique, on pourra rencontrer des scripts commençant
par #!/bin/bash ou #!/bin/zsh etc. Pour d'autres shells
UNIX. Dans la suite, nous utiliserons le Bourne shell. Bash et Zsh en
sont des extensions.
Commentaires
Le script est un langage de programmation à part entière et certaines
lignes d'instructions font parfois beaucoup de choses. Les commentaires
sont alors d'autant plus importants pour pouvoir se relire et être
relu. Dans un script Shell les commentaires sur une ligne commencent par
le caractère #
# ceci est un commentaire sur une ligne
Exécution
Pour pouvoir rendre un script exécutable, c'est-à-dire pouvoir le
lancer en tapant dans un terminal la commande ./script.sh. Il faut
le rendre exécutable. Pour cela, il faut modifier les droits de ce
fichier de la manière suivante: chmox +x script.sh
Les variables
Création
Le shell donne la possibilité de créer des variables, comme dans tous les langages de programmation. Contrairement aux langages compilés comme l'Ada, le C/C++, Java, etc. Les variables n'ont pas besoin d'être déclarées avant leur utilisation et ne sont pas typées. En fait les variables en shell sont toutes de type 'chaine de caractère'. En général dans un script shell, il est d'usage d'écrire les variables en majuscules afin de faciliter la lecture
Remarque : les variables Shell sont globales et donc restent accessibles partout dans un script
MESSAGE="hello world"
Ceci est la variable MESSAGE dans laquelle on a stocké la chaine de caractère hello world. Notez qu'il n'y a pas d'espaces des deux côtés du signe égal, cela ne fonctionnerait pas s'il y en avait. Le shell est assez pointilleux sur ce point contrairement à la plupart des langages compilés cités plus haut.
Utilisation
Pour récupérer et accéder à la valeur d'une variable, il faut faire
précéder son nom du caractère $, le tout entoure de guillemets. Par
exemple, pour afficher le contenu de la variable MESSAGE en console (en
utilisant la commande echo)
echo "$MESSAGE"
Remarque : Les guillemets ne sont pas toujours obligatoires dans la mesure où si la variable ne contient pas d'espaces, ça marchera sans : par exemple si on est absolument certain que la variable que l'on utilise représente un nombre. Avec les guillemets, cela marchera tout le temps, même si cela alourdit le code.
Par exemple, un cas ou les guillemets sont obligatoires : supposons que l'on parse une page HTML ligne à ligne et que l'on veut détecter des lignes de tableau commençant donc par : '\'
1 2 3 | |
Dans la variable DEBUT, on met le début de la ligne de code HTML.
On fait par exemple le test suivant:
1 2 3 4 5 6 7 | |
Si celle-ci commence par <img src=" cela ne fonctionnera pas à
cause du caractère <.
Par contre le code suivant marchera
1 2 3 4 5 6 7 | |
La présence de caractères spéciaux pour le Shell dans les variables (comme les espaces) implique l'utilisation des guillemets. De manière générale, il est conseillé de les mettre tout le temps, même si cela détériore la lisibilité du fichier
Concaténations
Les variables étant toutes du type chaîne de caractères, il est possible de les concaténer, ou de les compléter simplement en les écrivant côte à côte. Par exemple :
1 2 3 4 5 6 7 8 9 10 | |
Affectation du résultat d'une commande
Les résultats de commande : par exemple ls sont des chaines de
caractères et il est donc possible de les stocker dans une variable.
De manière générale, cela se fait de la manière suivante:
1 2 3 | |
Par exemple :
1 2 3 | |
Fonctions
Il est possible de faire des fonctions dans les scripts Shells. Ces dernières présentent les mêmes intérêts que dans le cas de la programmation classique en langages compilés : éviter les répétitions de code. Les fonctions peuvent prendre des paramètres, mais à l'inverse des langages compilés cela se fait de manière invisible sans même que l'on ait à déclarer quoi que ce soit, ce qui peut se révéler déroutant au premier abord. Voici comment déclarer une fonction :
1 2 3 4 | |
Le code peut utiliser les variables $1, $2, ... , $9 qui sont les
paramètres passés à la fonction. Quel que soit le nombre de paramètres
utilisés, l'en-tête de la fonction reste inchangé. Pour appeler une
fonction, on écrit son nom suivi de la suite des paramètres qu'on lui
passe, séparés par des espaces
ma_fonction PARAM_1 PARAM_2 PARAM_3 PARAM_4 PARAM_5 PARAM_6 PARAM_7 PARAM_8 PARAM_9
Par exemple, la fonction suivante
1 2 3 4 5 | |
aura pour effet d'écrire dans la console :
1 2 | |
c'est-à-dire remplacer l'écriture des deux echo. Cette fonction est sans paramètres et est appelée comme ceci
dire_bonjour
Un exemple de fonction avec 2 paramètres
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
Comme les paramètres ne sont jamais indiqués dans le prototype de la fonction, il est conseillé de les mettre en commentaire avant la fonction, comme ci-dessus, et ce, afin de rendre compréhension, relecture et débogage possible.
Utilisation :
1 2 3 4 5 | |
Commandes de base
Les pipes
Le pipe est un outil qui permet d'aligner des commandes Shell. Il est donc assez difficile de bien les expliquer sans connaitre de commandes. Cependant, dans la liste de commandes suivantes, il était très intéressant parfois de montrer quelques combinaisons assez pratiques. Donc, si vous ne connaissez pas les commandes utilisées dans cette section, il est conseillé de poursuivre en ignorant les parties/lignes contenant le caractère |.
Le pipe permet de faire correspondre la sortie d'une commande à l'entrée d'une autre. Une commande Shell peut être constituée d'autant de pipes que l'on veut.
Un pipe, avec deux commandes au total (ce qui est le minimum), s'écrit de la manière suivante
commande1 | commande2
Au fur et à mesure que la commande 1 produit son résultat, celui-ci est interprété par la commande 2. Bon, c'est un détail, mais cela fait que l'exécution est rapide.
L'exemple le plus utilisé est de faire un pipe avec grep en récepteur (piper avec grep dira-t-on ...)
Par exemple :
ls | grep "un_bout_de_nom_de_fichier"
grep ira chercher dans le résultat de ls une chaine de caractères avec un_bout_de_nom_de_fichier dedans
Les possibilités offertes par les pipes sont grandes :
par exemple :
1 2 3 | |
La première commande renvoie la liste du deuxième caractère du résultat de la commande ls -l et la seconde ligne de commande remplace pour chaque ligne du résultat de la commande ls -l la chaîne de caractère user par la chaîne hello user Par contre, on peut imaginer la commande suivante pour supprimer tous les fichiers dont le nom contient truc
ls | grep "truc" | rm
En fait cela ne marchera pas, car rm n'est pas fait pour lire un flux de données.
Pour que cela marche, il faut dire à rm que le résultat de la commande qui le précède passe dans ses paramètres.
Le mot clé pour cela est xargs
ainsi
ls | grep "truc" | xargs rm
fonctionnera.
De même, imaginons que l'on veuille chercher une chaine de caractères précise dans tous les fichiers d'un répertoire :
en supposant qu'il n'y a que des fichiers dans le répertoire courant, la commande
ls | grep "chaine de caracteres a chercher"
ne fera pas ce que l'on veut : elle va chercher la chaine de caractères dans le résultat de la commande ls
Ici, c'est xargs qui résout le problème :
ls | xargs grep "chaine de caracteres a chercher"
Cela n'est certes pas facile à comprendre du premier coup, (ni à expliquer clairement d'ailleurs). Il faut essayer et tâtonner un petit peu, après cela devient quasiment naturel de savoir si l'on met xargs ou pas.
En pratique, si la commande cible du pipe (ie celle qui est à droite) est capable de lire un fichier : cut, sed, grep ... , ce n'est pas la peine de mettre xargs, mais il y a des exceptions (cf l'exemple précédent)
Redirections
Il est possible de rediriger les sorties des commandes vers des fichiers.
Un simple chevron
>
pour mettre la sortie de la commande dans un fichier
Ex:
ls -l > contenu.txt
Doubles chevrons pour ne pas écraser le fichier s'il existe déjà et mettre le résultat de la commande a la suite de ce qu'il y a déjà dans le fichier.
Les erreurs éventuellement levées par les commandes ne sont pas considérées comme une sortie standard. Les simples et doubles chevrons ne les affectent donc pas. Pour rediriger la sortie d'erreur, l'opérateur est
2>
Il est possible de combiner > et 2> pour mettre la sortie d'erreur dans un autre fichier que la sortie standard, avec une commande ou un script Shell:
1 2 3 | |
Avec le shell bash, on peut mettre les deux sorties dans le même fichier avec l'opérateur
&>
(attention, cette syntaxe n'est pas POSIX et ne marchera pas avec tous les shells, typiquement pas avec le /bin/sh de Debian et Ubuntu)
cat
Plusieurs utilisations : affichage, édition et concaténation de fichiers
Sert à afficher le contenu d'un fichier appelé ainsi
cat fichier.txt
assez utile, cat (en version GNU) permet de numéroter les lignes (entre
autres, voir cat --help pour toutes les autres fonctionnalités)
cat -n fichier.txt
Sert à éditer un fichier
1 2 3 4 5 | |
EOF (pour End Of File) est la balise qui sert à indiquer à cat quand est-ce que l'on veut arrêter l'édition.
La chaine EOF n'est pas obligatoire, on peut mettre ce que l'on veut, mais il faut choisir une chaine de caractères que l'on ne souhaite pas mettre dans le fichier. Par exemple les mots THE_END, ou C_FINI feront parfaitement l'affaire, c'est juste une convention de terminer avec EOF, rien de plus.
Dans la commande ci-dessus, si le fichier existe, son contenu sera effacé (ou pas : en fait cela dépend du Shell que vous utilisez, mais parfois il vous indiquera que le fichier existe et qu'il ne peut pas l'écraser)
Pour écrire à la suite d'un fichier et donc conserver ce qu'il y a déjà d'écrit dedans, il faut utiliser deux chevrons au lieu d'un seul
1 2 3 4 5 | |
De manière générale pour les redirections de flux dans les fichiers : un
chevron > pour effacer le contenu s'il existe, créer le fichier s'il
n'existe pas et deux chevrons >> pour écrire à la suite du fichier,
et également le créer s'il n'existe pas.
cat sert également à concaténer des fichiers et afficher le résultat en console. On pourra donc rediriger le flux dans un fichier si l'on veut enregistrer cela.
cat fichier1.txt fichier2.txt > resultat.txt
Sur cet exemple on concatène deux fichiers, mais on peut en concaténer autant que l'on veut
head et tail
head
Permet d'afficher les premières lignes d'un fichier (10 premières par défaut, mais on peut lui préciser combien)
1 2 3 4 | |
tail
Pareil que head mais en partant de la fin d'un fichier
1 2 3 4 | |
Sélectionner de la ligne L1 a L2
À titre d'illustration, voici comment extraire la portion du fichier contenu entre la ligne L1 et la ligne L2
(Une version plus efficace serait
sed -n $L1,$L2p fichier.txt
).
Cas particulier: sélectionner la ligne N
Utilisation combinée de head et tail au moyen d'un pipe
1 2 | |
Cas général
Il faut juste calculer le nombre de lignes à extraire : L2-L1+1 ou L2-L1
selon si l'on veut sélectionner les extrêmes ou pas
1 2 | |
grep
Description
Permet de chercher une chaîne de caractères parmi un flot de données (fichier texte, ou directement résultat de commande affiché en console en utilisant des pipes)
Utilisation de base :
grep "chaine de caractere a chercher" fichier_ou_chercher.extension
grep fonctionne ligne à ligne : il affichera par défaut, toutes les lignes contenant la chaîne de caractères à chercher.
On peut aussi faire avec un pipe :
cat fichier.txt | grep "chaine a chercher"
Certains diront que c'est un usage inutile de cat. Cependant, avec cette commande la chaîne à chercher est mise an relief dans le terminal.
Quelques options utiles
L'option -n permet de numéroter les lignes ce qui peut s'avérer
pratique par exemple si on veut supprimer la ligne du fichier.
grep -n "chaine de caractere a chercher" fichier_ou_chercher.extension
C'est équivalent à un
cat -n fichier.extension | grep "chaine a chercher"
L'option -v permet de sélectionner toutes les lignes sauf celles qui
contiennent la chaine de caractères spécifiée.
Exemple :
grep -v "indesirable" fichier.extension
Toutes les lignes contenant le mot indésirable dans le fichier fichier.extension ne seront pas affichées
L'option -A (attention, pratique, mais pas portable) permet d'afficher
un nombre de lignes directement après la ligne où se trouve la chaine à
chercher. Ce nombre de lignes est à spécifier juste après. (A pour
after)
Exemple
grep -A5 "trouver" fichier.extension
affichera les 5 lignes suivant chaque ligne où se trouve le mot trouver
L'option -B (pour before), exactement comme -A mais pour les lignes
avant cette fois.
L'option -a combine les deux précédentes options en affichant un
certain nombre de lignes avant et après celle contenant la chaine de
caractères cherchée.
grep est aussi compatible avec les expressions régulières : pour chercher toutes les lignes contenant un chiffre, une solution est
grep [0-9] fichier.extension
find
La commande find est en quelque sorte un ls récursif qui
cherche des fichiers ou dossiers dans toute une arborescence à partir
d'un répertoire racine spécifié (./ par défaut)
Par exemple :
find /home/paul/projet_c/ -name "*.c"
affichera tous les fichiers dont l'extension est en .c dans le répertoire projet_c de paul.
Plus précisément, la commande affichera les fichiers avec tous leurs chemins d'accès en incluant celui spécifié, en l'occurrence : /home/paul/projet_c/
Par exemple la recherche pourrait donner le résultat suivant
1 2 3 | |
on peut chercher plusieurs choses grâce à l'option -o (pour or) :
find /home/paul/projet_c/ -name "*.c" -o -name "*.h"
cherchera aussi les fichiers .h
On aura donc, par exemple, le résultat suivant :
1 2 3 4 5 | |
wc
Compteur de caracteres.
wc fichier.txt
Affichera dans l'ordre : le nombre de lignes, mots et caractères dans fichier.txt.
L'option -l est très utile pour compter les lignes d'un fichier
wc -l fichier.txt
ou pour avoir directement le résultat (sinon le nom du fichier est rappelle a cote) :
cat fichier.txt | wc -l
-m pour avoir le nombre de caractères et -w (word) pour le nombre de
mots
cut
En considérant qu'une sortie console, un fichier sont des tableaux de caractères, cut permet de faire des découpes suivant l'axe vertical. cut permet donc de découper (au sens de sélectionner certaines parties) des chaines de caractères.
On va prendre pour exemple la chaine de caractères
PHRASE="bonjour chères lectrices et chers lecteurs, comment allez vous"
Il est possible de définir quels délimiteurs utiliser pour cette chaine
de caractères. Comme c'est une phrase avec des mots, avec l'option
-d suivie du délimiteur voulu. On peut par exemple choisir l'espace
" " pour sélectionner les mots que l'on veut dans cette phrase.
- Pour sélectionner le 3 ième mot de la phrase, la commande sera donc
echo "$PHRASE" | cut -d" " -f3 - Si on veut sélectionner les 3 premiers mots
echo "$PHRASE" | cut -d" " -f-3 - Si on veut sélectionner à partir du troisième mot
echo "$PHRASE" | cut -d" " -f3- - Si on veut sélectionner du troisième au sixième mot compris
echo "$PHRASE" | cut -d" " -f3-6
Question : Si on veut sélectionner le dernier mot sans connaitre combien il y a de mots ?
(indice : aller voir rev)
Application tres pratique : sélectionner uniquement le nom de fichier en sortie de find qui lui affiche tout le path à partir du répertoire qu'on lui a précisé.
Ici sur l'exemple il n'y a qu'une seule ligne, mais cut marche sur plusieurs lignes et fera des découpes (on peut aussi appeler ca des sélections aussi ...) verticales.
On peut aussi directement spécifier à cut les numéros de caractères que l'on veut découper. Cela se fait avec l'option -b Les caractères se numérotent naturellement de gauche a droite, en commençant à 1.
- sélection du 42 ieme caractère dans la phrase ci-dessus
echo "$PHRASE" | cut -b42 - jusqu'au 42
echo "$PHRASE" | cut -b-42 - depuis le 42
echo "$PHRASE" | cut -b42- - du 24 au 42
echo "$PHRASE" | cut -b24-42
rev
Permet de renverser une chaine de caractères
echo bonjour | rev
retourne
ruojnob
Exemple :
sed
sed (Stream EDtior) est un éditeur de fichiers et procède ligne par ligne. C'est une commande très puissante, dont l'utilisation la plus courante est de remplacer des chaînes de caractères dans des fichiers (ou à l'intérieur d'un pipe).
Utilisation basique
Pour remplacer toutes les chaînes de caractères par une autre
sed -e "s/chaine a remplacer/nouvelle chaine/g" fichier
Pour remplacer la première occurrence sur chaque ligne de la chaîne de caractère spécifiée, on ne met pas le g
sed -e "s/chaine a remplacer/nouvelle chaine/" fichier
Certains caractères sont à échapper comme le point . ou les doubles quotes "
et également le slash \, car il est utilisé comme délimiteur dans la
commande. Si la chaîne à remplacer comporte beaucoup de slash, on peut
utiliser d'autres caractères pour délimiter : le # peut être un bon
choix
Le début de ligne est codé par ^
La fin de ligne par $
Le retour à la ligne pour spécifier par quoi on veut remplacer: \n
(comme en C)
Tabulation : \t
Par défaut, le résultat s'affiche en console. Pour modifier le fichier
traité, il faut utiliser l'option -i
sed -i -e "s/"chaine a remplacer"/"nouvelle chaine/g" fichier
Enregistrements
sed permet également de faire du pattern matching ligne à ligne et supporte les expressions régulières :
Supposons que l'on veuille détecter toutes les lignes d'un fichier qui
à n'importe quel endroit contiennent la chaîne de caractère
"_____" (soit 5 underscore accolés) suivi d'un nombre de
caractères quelconques et de la chaîne "ttttt" puis un nombre de
caractères quelconques jusqu'à la fin de ligne.
Par exemple la ligne suivante devrait être détectée :
Apollo 11 est la première mission _____ spatiale à avoir conduit un ttttt homme sur la Lune.
Supposons que l'on ne veuille conserver que ce qu'il y a entre
_____ et ttttt :
la commande sed suivante fait cela :
sed -e "s/\(.*\)_____\(.*\)ttttt\(.*\)/\2/"
Les expressions
\(.*\)
correspondent aux enregistrements : les \ sont là pour échapper les parenthèses qui ont un sens pour sed autrement.
Le point est là pour désigner n'importe quel caractère et l'astérisque sa répétition quelconque à partir de 0. Ici donc sed va enregistrer n'importe quelle chaîne de caractères et s'arrêtera quand il repèrera les 5 underscores.
Le \2 représente le second enregistrement c'est-à-dire ce qui se trouve entre _____ et ttttt.
Il est possible de faire jusqu'à 9 enregistrements dans un sed qui seront restitués par \1 ... \9
Informations supplémentaires
Plus d'infos sur sed ici
http://anaturb.net/sed.htm
bc
bc (binary calculator) est un outil permettant de faire des calculs, entier et a virgule flottante principalement.
On peut l'utiliser de la maniere suivante (mais bien sur ce n'est pas la seule facon de l'utiliser)
echo "scale=``<nombre de chiffres apres la virgule voulus>; <calcul a effectuer>" | bc
Par exemple, si on veut faire le rapport entre deux variables, avec une precision au centieme :
echo "scale=2;$VAR_1/$VAR_2"| bc
L'argument scale n'est pas obligatoire. Sa valeur est par défault 0 si on ne précise rien, ce qui permet de faire des calculs avec des résultats entiers
bc permet egalement de faire des comparaisons sur des nombres et renvoie soit 0 pour vrai soit 1 pour false (comme en C)
Par exemple
echo "7.77 < 42.42" | bc
renverra 1
On a donc ici un outil pour faire des tests sur des entiers flottants ... (le shell ne les supportant pas les comparaisons de flottants sans utiliser bc).
1 2 3 | |
sort
sort est une commande qui permet de trier des chaines de caractères par ordre alphabétique. Donc caractère par caractère, en partant de la gauche.
Pour trier des nombres, attention : 42 est plus grand que 7 mais par
défaut, sort compare d'abord 7 et 4 et placera 7 avant 42 donc.
L'option -n de sort permet de gérer ce cas, en faisant un tri
numérique et non alphabétique.
uniq
La commande uniq permet d'éliminer les doublons dans une liste triée
convert
convert n'est pas une commande Shell de base. En fait c'est une commande de ImageMagick, logiciel pour la manipulation d'images. Elle est très pratique car elle permet de convertir rapidement des fichiers dans tous les formats d'images (PNG,JPG,GIF ...) mais aussi de convertir un fichier PDF (donc vectoriel en image).
Sur Ubuntu elle est installée de base mais ce n'est peut être pas le cas dans d'autres distributions.
Conversion redimensionnement d'images
Quelques exemples :
1 2 3 4 | |
On peut aussi redimensionner via l'option resize
convert image.gif -resize 100x200 image.jpg
Conversion de PDF en image
Pour la conversion d'un PDF en image, vu que le format PDF est vectoriel, on peut choisir la qualité de l'image en sortie : Par exemple
convert -density 400 fichier.pdf -resize 25% fichier_.gif
l'option density fait référence aux dpi.
Pour faire varier la résolution de l'image en sortie il faut jouer sur les options density et resize
Couper une image
L'option -crop permet de couper une image, d'en sélectionner une partie
convert image.gif -crop 100x200+10+20 image_out.gif
Crée l'image image_out.gif de taille 100 pixels de large et 200 pixels de haut, qui est une partie de image.gif, dont le coin supérieur gauche correspond au point de coordonnées (10,20) dans image.gif.
En général, dans la programmation graphique, l'origine du repère est prise dans le coin supérieur gauche des images, et c'est le cas ici. Les axes des abscisses et des ordonnées restent toujours respectivement horizontaux et verticaux, le premier pointe vers la droite et le second vers le bas.
Générer des graphiques dans des scripts
Cela est possible (entre autres) avec le logiciel de statistiques R. (pour les premières années un coup d'apt-get/aptitude install ...)
Un moyen de le faire est de rentrer la commande qui générera le graphique dans un fichier texte à coups de cat (comme vu plus haut)
1 2 3 4 5 | |
Puis on affiche le tout avec cat et on pipe avec R avec l'option save
cat R_command.txt | R --save
Penser à nettoyer les fichiers temporaires après. Cela produit un fichier PDF : Rplots.pdf contenant le graphique en question.
Il est possible de le convertir a sa guise ensuite grâce à convert vue plus haut
Envoyer un mail
On peut utiliser pour cela la commande mailx
Exemple :
1 2 3 4 5 | |
Instructions de contrôle
Le Shell permet d'effectuer les instructions de contrôle basiques et classiques en programmation : if, while et for Attention à bien respecter la forme décrite dans les exemples ci-dessous car le Shell est très sensible aux fautes de syntaxe/typographie. Un espace en trop ou en moins peut faire que le Shell ne comprendra pas ce que vous voulez faire.
L'instruction if
L'instruction if s'écrit de la manière suivante :
1 2 3 | |
ou encore
1 2 3 4 | |
La présence du point virgule est équivalente à un retour chariot.
Notez bien la présence d'un espace après le crochet ouvrant et avant le crochet fermant...
On peut donner ici les exemples les plus courants de condition.
On désigne par
VAR_1 et VAR_2
deux variables Shell (donc des chaines de caractère par défaut).
La première condition la plus utilisée est de comparer $VAR_1 et
$VAR_2 en tant que chaines de caractères
1 2 3 4 | |
La aussi notez la présence des espaces de part et d'autre du signe "="
On peut bien sûr comparer une variable avec une chaine de caractère ou encore deux chaines de caractères différentes et fixées (ce qui présente quand même peu d'intérêt)
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Conditions : tests possibles
On peut effectuer des tests sur les variables (ou des chaines de caractères, cela revient au même) :
-epour tester l'existence (exists)-dpour un dossier (directory)-fpour un fichier (file)
1 2 3 4 5 | |
1 2 3 4 5 | |
1 2 3 4 5 | |
Le Shell permet de faire des tests en interprétant des variables comme des nombres.
-eqégal-nedifférent (not equal)-leinférieur ou égal (lower equal)-gesupérieur ou égal (greater equal)-ltinférieur à (lower than)-gtsupérieur à (greater than)
Exemple
1 2 3 4 5 6 7 | |
ou encore
1 2 3 4 5 6 | |
Tester si une variable est vide
Dans un script, on peut vouloir faire un test sur le résultat d'une commande : en particulier savoir si elle a renvoyé quelque chose ou pas. Par exemple un grep. L'idée est de mettre le résultat de la commande dans une variable et concaténer cette variable avec n'importe quoi : typiquement :
1 2 3 4 5 | |
Remarque : ici les guillemets dans le test du if sont obligatoires sinon cela plantera à partir du moment où l'on aura plus de deux éléments dans le répertoire courant : en effet, cela implique que la variable VAR contiendra des espaces donc si l'on ne met pas de guillemets, le Shell interprètera chaque mot séparément au lieu d'un seul bloc contenant des espaces.
Attention, la condition d'égalité est assez sensible aux espaces,
tabulations, retour ligne. Il est préférable de ne prendre que la
premiere ligne de résultat de la commande (grace á la commande head -1)
et de supprimer espaces et tabulations (sed)
Ainsi pour reprendre l'exemple :
VAR=$(ls | head -1 | sed -e s/" "/""/g -e s/"\t"/""/g)
Aura plus de chance de fonctionner
Negation
La négation se fait comme en C/C++, Java : avec un point d'exclamation
Exemple
1 2 3 4 | |
and et or pour les conditions
-apour and-opour or
1 2 3 4 | |
L'instruction for
L'instruction for permet de faire une boucle sur un ensemble. Un ensemble est comme toujours en Shell, une chaine de caractères.
Les éléments de l'ensemble sont les "mots" constituant la chaîne de caractère, c'est-à-dire les suites de caractères contiguës entre deux espaces ou tabulations.
Par exemple :
"ceci est un ensemble"
est un ensemble qui comporte quatre éléments
Syntaxe et exemple de boucle for
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
Remarque: Si on met des guillemets autour de $ENSEMBLE, la boucle
for iterera sur un seul élément (ELEMENT=valeur1 valeur2 valeur3). Si on
ne met pas de guillemet, le shell va découper le contenu de la variable
selon les blancs, et va itérer sur les trois valeurs (valeur1, valeur2
et valeur3).
Comment créer des ensembles ? Une solution est d'utiliser la sortie de n'importe quelle commande produisant une suite d'éléments séparés par des blancs.
Attention: On serait tenté d'utiliser la commande ls pour produire un ensemble. C'est une très mauvaise idée :
1 2 3 4 | |
ou encore
1 2 3 4 | |
Dans les deux cas, on va exécuter la commande ls, et redécouper la sortie de ls après coup. Si un fichier contient un espace ou autre caractère spécial du shell, la boucle ne marchera pas. Par contre, la boucle suivante :
1 2 3 4 | |
fait ce qu'elle doit faire dans tous les cas : l'expansion du jocker « * » étant faite après l'interprétation des blancs, les caractères spéciaux ne posent aucun problème ici. Par ailleurs, cette syntaxe évite de lancer une commande externe ls, et est donc plus efficace.
Une autre utilisation intéressante de la boucle for est d'itérer sur les arguments d'une fonction ou d'un script :
1 2 3 4 | |
La commande seq
Faire une boucle sur des entiers de n1 à n2 :
Cela peut se faire au moyen d'une boucle while mais on peut le faire également grâce à la commande seq
1 2 3 4 | |
L'instruction while
La syntaxe d'une boucle while est la suivante:
1 2 3 4 | |
où condition est exactement du même type que ceux des structures if
Pour faire une boucle for allant d'un entier n1 a un entier n2 on peut faire ainsi
1 2 3 4 5 6 7 8 9 | |
Exemple(s)
Vous avez une arborescence dans laquelle se trouve des fichiers jpg (imaginons que ce sont des fichiers scannés et que votre scanner ne les convertisse pas directement sous format pdf). Vous voulez sélectionner tous ces fichiers et les convertir en pdf sans a avoir a taper 1000 fois
convert fichier.jpg fichier.pdf
Le script suivant convertit en pdf tous les fichiers jpg contenus dans l'arborescence courante et les rappatrie dans le repertoire courant
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Trouver tous les fichiers java dans l'arborescence courante qui contiennent la chaine de caractères passée en paramètre :
1 2 3 4 5 6 7 8 9 | |
Les outils UNIX sur windows ?
Le plus simple pour avoir accès à la partie "shell" d'Unix avec la machine virtuelle dédié à Linux et intégrée dans Windows: WSL2.
La plupart des outils unix sont aussi utilisables aussi directement dans windows, sans machine virtuelle.
Il est possible d'émuler un shell UNIX avec les outils associés (terminal, commandes de base, ...) sur Windows ce qui peut s'avérer pratique pour profiter des nombreuses fonctionnalités vues ici.