Shell

Un interpreteur de commandes ou « shell » permet d’acceder au systeme de maniere sécurisée, sans avoir a écrire de programmes et en limitant le risque de le rendre inutilisable.

Il se présente sous la forme d’une invite de commandes qui interpret puis execute les commandes entrées par l’utilisateur.

Cette vidéo explique entre autres la place du “shell” dans un systeme UNIX (vers 5:00), et differents éléments de la philosophie d’UNIX : programmes de petite taille s’imbriquant les uns avec les autres, abstraction des differents composants materiels qui permet de lire et ecrire n’importe quoi depuis et vers n’importe quoi avec un seul programme.

Un programme UNIX est préférablement une brique d’une ligne de commande invoquée par un « shell » : avant d’écrire des programmes en ligne de commande il convient de maitriser les bases du shell.

SH, Dash, KSH, CSH, BASH, ZSH

Il existe de nombreux shells qui ajoutent des fonctionnalités à ceux qui existaient avant eux, ou bien incompatibles totalement avec les shells existants déjà.

Une norme POSIX garantit certainent fonctionnalités et un socle commun pour écrire des scripts shells portables.

SH est le shell “originel” et bash, ksh, dash en sont dérivés. Zsh est lui dérivé de Ksh.

CSH est un shell inspiré du langage C plutot que de la syntaxe de SH. Il a été populaire mais décrié aujourd’hui : csh programming considered harmful https://web.mit.edu/ghudson/info/csh.whynot 🌍⤴ .

Nous utiliserons le shell : dash, qui est un shell léger (man dash | wc -l contre man bash | wc -l en donne une idée).

Ce shell est livré par défaut avec la plupart des distributions Linux (WSL y compris) et sur MacOS. Ce qui est valide avec dash le sera aussi sur bash ou zsc alors que la réciproque n’est pas vrai.

Taper dash dans une invite de commandes ouvre une session, quit ferme la session. man dash affiche un manuel d’usage du shell sans doute plus complet que ce chapitre.

rc est également un shell léger avec un cours succint et bien expliqué (en anglais) : https://doc.cat-v.org/plan_9/4th_edition/papers/rc 🌍⤴

Commandes de base

Voilà quelques exemples de commandes que peut comprendre un shell (depuis le manuel de rc) :

date
cat /lib/news/build
who >user.names
who >>user.names
wc <file
echo [a-f]*.c
who | wc
who; date
vc *.c &
mk && v.out /*/bin/fb/*
rm -r junk || echo rm failed!

Affiche la date, affiche le contenu de /lib/news/build, écrit les utisateurs connectés dans le fichier user.names, rajoute à la fin une deuxieme fois les utilisateurs connectés, compte les mots du fichier file, affiche tous les fichiers dans le répertoire courant qui commencent pas une lettre entre “a” et “f” et se terminent par “.c”, compte le nombre d’utilisateurs connectés, exécute successivement who et date en une seule commande, exécute la commande vc puis la relègue en tache de fond non bloquante, enchaine les commandes mk et v.out uniquement si la commande mk a réussi, exécute rm, puis echo si la commande rm a échoué.

Creer des fichiers et traitement en masse

On va commencer par creer 10 fichiers nommés 1toto.c, 2toto.c, etc.

for i in 1 2 3 4 5 6 7 8 9 10; do
 touch ${i}toto.c
done

ou encore

for i in $(seq 1 10); do
 touch "$i"toto.c
done

Si on écrivait simplmenent $itoto.c, l’interpreteur recherche la variable “itoto.c” et retourne une chaine vide si la variable n’existe pas, pour isoler la variable du reste de la chaine il faut écrire soit "$i"toto.c, soit $i"toto", ou encore $i""toto ou bien $i''toto, ou bien ${i}toto.

Avec bash et zsh, une manière plus concise de procéder est touch {1,2,3,4,5,6,7,8,9,10}toto.c, ou encore touch {1..10}toto.c.

On a vu que l’interpreteur concatene les chaines de caractere et traite ' et " comme délimiteur. echo "to""to" affiche toto. Si on veut utiliser ces caractères en tant que tels, il faut les entourer avec les autres guillemets : echo '"'L"'"histoire sans fin'"'.txt affiche "L'histoire sans fin".txt.

Les motifs de substitution

Les caractères [, ? et * dans un argument ont une signification particuliere. dash autorise touch to*to.c, mais pas bash, il vaut mieux en général entourer ces caractères entre guillements : touch to'*'to.c.

Pour rechercher des fichiers contenant ces caractères, les entourer de guillements echo *'*'*.

$ echo ??toto*
10toto.c
$ echo ?to*
1toto.c 2toto.c 3toto.c 4toto.c 5toto.c 6toto.c 7toto.c 8toto.c 9toto.c
$ echo [1-5]
[1-5]
$ echo [12345]t*
1toto.c 2toto.c 3toto.c 4toto.c 5toto.c
$ echo [1-5]*
10toto.c 1toto.c 2toto.c 3toto.c 4toto.c 5toto.c
$ echo [1-5]t*
1toto.c 2toto.c 3toto.c 4toto.c 5toto.c
$ echo [1-36-8]t*
1toto.c 2toto.c 3toto.c 6toto.c 7toto.c 8toto.c
$ echo [!1-2]t*
3toto.c 4toto.c 5toto.c 6toto.c 7toto.c 8toto.c 9toto.c
$ echo [!1-36-8]t*
4toto.c 5toto.c 9toto.c

? se substitue à un seul et unique caractères, * se substitue à n’importe quelle succession de caractères, [] permet de spécifier une classe de caractères, un tiret - specifie une plage de caractères.

Les caracteres /, . et .. ne sont pas considérés dans les substitutions, la recherche de fichiers ne se fait donc pas ni dans les répertoires descendants, ni parents, ni recursivement courant.

Lors