Compléments sur le shell
Fonctions shell
Un script shell est un petit programme écrit dans le langage du shell. C'est un fichier contenant des commandes et des constructions similaires à celles trouvées dans les langages de programmation plus "évolués".
La première ligne d'un tel fichier doit être
#!/bin/bash
afin que le système le reconnaisse comme script shell.
On peut définir une fonction dans un script bash de la manière suivante :
function fonction_de_test() {
CMD1
CMD2
CMD3
...
}
Cela permet d'ajouter une commande : une fois que le fichier est lu par le shell, par exemple par
$ source FICHIER
la commande fonction_de_test
effectuera les commandes
CMD1
, CMD2
, etc.
Comme avec Python et Idle, le fait d'avoir écrit une fonction n'est pas suffisant pour pouvoir l'exécuter. Il faut "charger" le fichier contenant la définition des fonctions avant de pouvoir les utiliser.
Avec Idle, il fallait choisir le menu "Run", "Run module" (ou le raccourci clavier "F5").
Dans le shell, on peut charger un fichier avec la commande
$ source FICHIER
D'autres fonctionnalités intéressantes sont :
- instruction
echo
-
On peut faire un affichage simple avec la commande
echo
echo "FIN de la fonction "
- variables
-
On peut définir des variables du shell avec le signe
=
:var="..."
Attention, il ne faut pas mettre d'espace autour du signe
=
.Pour utiliser la valeur d'une variable, il faut précéder son nom du signe
$
echo "La valeur de var est $var"
Pour initialiser une variable avec le résultat d'une autre commande, il faut utiliser
var=$(CMD)
où
CMD
est la commande à exécuter. - conditionnelles
-
Pour faire des instructions conditionnelles, on peut utiliser un
if
. La syntaxe estif [ TEST ] then ... elif [ TEST ] then ... elif [ TEST ] then ... else ... fi
Attention, les espaces sont obligatoires après le symbole
[
et avant le symbole]
!TEST
est une condition, qui porte en général sur des variables :-
-z "$var"
pour tester si la variable est vide ou non, -
-f "$var"
pour tester si la variable contient un nom de fichier qui existe, -
"$var" == "hello"
pour tester si la variable contient la chainehello
, -
etc.
La liste des tests possibles est accessible avec
$ man test
-
Boucle sur les arguments d'une fonction
Les boucles du langage bash ressemblent à
for i in LIST
do
...
done
où LIST
est une liste de chaines, séparées par des espaces. Par
exemple
$ for i in chat chien souris
> do
> echo "animal : $i"
> done
animal : chat
animal : chien
animal : souris
Les arguments d'une fonction sont automatiquement mis dans une variable
spéciale appelée $@
. Si le fichier script.sh contient
#!/bin/bash
function animaux() {
for a in "$@"
do
echo "animal : $a"
done
echo "FIN de la fonction"
}
alors l'exécution donne
$ source script.sh
$ animaux chat chien chauve souris canard
animal : chat
animal : chien
animal : chauve
animal : souris
animal : canard
FIN de la fonction
$ animaux
FIN de la fonction
Arguments individuels d'une fonction
Comme expliqué dans la section boucle sur les
arguments d'une fonction, la liste des arguments d'une fonction est
appelée $@
.
Pour accéder aux premiers arguments individuellement, il faut utiliser les
variables $1
, $2
, ... $9
.
Pour accéder aux arguments suivants (après le numéro 9), il faut "décaler"
les arguments. La commande shift
supprime le premier argument et
décale les suivants. Ainsi, après un shift
, la variable
$1
contient l'argument numéro 2, etc.
Par exemple, si le fichier args.sh contient
#!/bin/bash
function montre_args() {
echo "Tous les arguments : $@"
echo "Argument 1: $1"
shift
echo "Autres arguments : $@"
}
on aura
$ source ./args.sh
$ montre_args ananas pomme poire kiwi
Tous les arguments : ananas pomme poire kiwi
Argument 1: ananas
Autres arguments : pomme poire kiwi
Opérations arithmétiques en bash
Les calcul arithmétique en bash doivent obligatoirement se trouver dans un
$((...))
.
$ echo "1 + 2"
1 + 2
$ echo "$((1 + 2))"
3
On peut utiliser des variables, et stocker le résultat dans une variable:
$ V=117
$ echo "la valeur de V est $V"
la valeur de V est 117
$ V=$(( $V / 2 ))
$ echo "la valeur de V est $V"
la valeur de V est 58
Attention le résultat d'une opération arithmétique n'est pas une commande :
$ $((1 + 2))
bash: 3 : commande introuvable
Quelques commandes utiles
Commande basename
, dirname
et realpath
Les commande basename
et dirname
permettent
d'afficher la partie finale / initiale d'un chemin d'accès :
-
basename CHEMIN
n'affichera que la dernière partie du chemin, c'est à dire le nom du fichier, -
dirname CHEMIN
n'affichera que les première parties du chemin, c'est à dire le chemin du répertoire.
Par exemple, si CHEMIN
vaut
/home/hyvernat/info202/TP/sujets/TP5/correction/corbeille/corbeille.sh
,
on aura
$ dirname $CHEMIN
/home/hyvernat/info202/TP/sujets/TP5/correction/corbeille
$ basename $CHEMIN
corbeille.sh
La fonction realpath
permet de transformer un chemin relatif en
chemin absolu:
$ pwd
/home/hyvernat/info202/TP/sujets/TP5/correction
$ realpath ./corbeille/corbeille.sh
/home/hyvernat/info202/TP/sujets/TP5/correction/corbeille/corbeille.sh
Commandes head
et tail
Les commandes head
et tail
permette de récupérer
des lignes au début ou à la fin d'un fichier :
-
head FICHIER
affiche par défaut les 10 premières lignes deFICHIER
. Il est possible de changer cette valeur avechead -n N FICHIER
. Pour afficher toutes les lignes, sauf lesN
dernières, on peut utiliserhead -n -N FICHIER
. -
tail FICHIER
affiche par défaut les 10 dernières lignes deFICHIER
. Il est possible de changer cette valeur avectail -n N FICHIER
. Pour afficher toutes les lignes à partir de laN
ème, on peut utilisertail -n +N FICHIER
.
Commande touch
La commande touch
permet de modifier la date de dernier accès et
date de dernière modification d'un fichier :
$ ls -l examen.pdf
-rw-r--r-- 1 hyvernat hyvernat 114087 2017-04-10 09:58:14 examen.pdf
$ touch -t 200902132331.30 examen.pdf
-rw-r--r-- 1 hyvernat hyvernat 114087 2009-02-13 23:31:30 examen.pdf
$ touch examen.pdf
-rw-r--r-- 1 hyvernat hyvernat 114087 2017-04-24 09:38:44 examen.pdf
La date donnée à touch
a la forme SSAAMMJJhhmm.ss
,
où SS
(siècle), AA
(année) et .ss
(seconde) sont facultatifs.
Commandes cut
et tr
La commande tr
permet de modifier certains caractères, ou d'en
supprimer. Cette commande agit sur l'entrée standard :
-
pour changer des caractères on donne simplement deux chaines
$ echo "giraffe" | tr "abcde" "ABCDE" girAffE
Les caractères de la première chaine sont remplacés par ceux de la deuxième liste. (Il faut que les deux listes aient la même taille...)
-
pour supprimer des caractères, on utilise l'option
-d
$ echo "giraffe" | tr -d "abcde" girff
En effet, si on supprime les a, b, c, d et e de la chaine giraffe, on obtient girff.
La commande cut
permet de récupérer seulement certaines parties
d'une chaine : on précise un délimiteur, les numéros des champs qui nous
intéressent. Cette commande agit sur l'entrée standard :
-
pour récupérer le deuxième mot (délimiteur : espace)
echo "Hello World !" | cut -d" " -f2 World
-
pour récupérer les composantes rouge et bleue d'une couleur RR,GG,BB
echo "b0,62,bf" | cut -d"," -f1,3 b0,bf
Commande file
La commande file
essaie de deviner le type des fichiers donnés
en argument :
$ file test.py log tmp TP4 Lac.jpg
test.py: Python script, ASCII text executable
log: ASCII text
tmp: empty
TP4: directory
Lac.jpg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 72x72,
segment length 16, Exif Standard: [TIFF image data, big-endian, direntries=14],
baseline, precision 8, 320x480, frames 3
Il est possible d'afficher un type de fichier plus succinct : le type MIME en donnant
l'option -i
à la commande :
$ file -i test.py log tmp TP4 Lac.jpg
test.py: text/x-python; charset=us-ascii
log: text/plain; charset=us-ascii
tmp: inode/x-empty; charset=binary
TP4: inode/directory; charset=binary
Lac.jpg: image/jpeg; charset=binary
Il n'est parfois pas nécessaire d'afficher le nom du fichier. Cela se fait en
ajoutant l'option -b
:
$ file -bi test.py log tmp TP4 Lac.jpg
text/x-python; charset=us-ascii
text/plain; charset=us-ascii
inode/x-empty; charset=binary
inode/directory; charset=binary
image/jpeg; charset=binary
La commande du
La commande du
(disk usage) prend une liste de fichiers en
argument et affiche la taille occupée (en Kio) par chaque fichier. L'option
-c
permet d'afficher également l'espace total utilisé par les
fichiers et l'option -h
permet d'afficher un taille en utilisant
des unités "raisonnables" (k, M, G).
Par exemple :
$ du -ch *.html *.pdf
12K Fabrication d'un micro-processeur.html
56K cours.html
2.2M 2I010_2016_support.pdf
12K survie.pdf
12K t.pdf
2.3M total
Attention, sans aucun argument, la commande du
calcule la
taille occupée par tous les fichiers contenu dans le répertoire courant et ses
sous-répertoires.
Informations EXIF
Les données EXIF peuvent contenir de nombreuses informations renseignées par l'appareil photo :
-
date de prise
-
localisation de la photo (si l'appareil est équipé d'un GPS)
-
temps d'exposition
-
flash
-
...
exiftool
est un utilitaire qui permet de récupérer ces
informations
$ exiftool Bauges.jpg
...
Create Date : 2011:08:11 12:41:02.00
Shutter Speed Value : 1/200
...
Flash : No Flash
Focal Length : 32.0 mm
...
Il est possible de récupérer un unique champs de la manière suivante :
$ exiftool -CreateDate Bauges.jpg
Create Date : 2011:08:11 12:41:02.00
L'option -b
est utile dans les scripts car elle permet de
récupérer seulement la valeur du champs :
$ exiftool -b -CreateDate Bauges.jpg
2011:08:11 12:41:02.00$
Si la commande exiftool
n'existe pas sur votre système, vous
pouvez :
-
installer le paquet libimage-exiftool-perl (Debian / Ubuntu) si vous avez les droits administrateurs,
-
télécharger le programme exiftool-10-50 (http://www.sno.phy.queensu.ca/~phil/exiftool/) et :
-
extraire le contenu de l'archive
$ tar zxvf Image-ExifTool-10.50.tar.gz
-
créer un alias pour la commande
$ alias exiftool="CHEMIN/Image-ExifTool-10.50/exiftool"
où
CHEMIN
est le chemin absolu de téléchargement. (Attention, si vous fermez votre terminal ou votre session, il faudra recréer l'alias.)
-