Contributeurs, les sont là pour vous aider, supprimez-les une fois le problème corrigé ou le champ rempli !
Nota : Les autres wiki :
Parmi les opérateurs d'enchaînement de commandes (voir les opérateurs de contrôle)
& && ; ( ) { }
Pour ce qui concerne les opérateurs de contrôle du point de vue de l'enchaînement conditionné (avec&&
et||
)
voir : état de sortie et code de retour.
&
: parallélisme.Toutes les commandes sont exécutées parallèlement.
Dans l'exemple ci-dessus, chaque commande étant traitée par un sous-shell,
le résultat d'une commande ne peut pas être conservée dans un même processus,
afin que chaque commande puisse “travailler” en rapport au résultat de la
commande précédente.
Par exemple, il faut que le fichier créé soit “connu” du shell pour qu'il puise être ouvert par “gedit” dans ce même shell.)
&&
: succession conditionnée.La commande suivante est exécutée successivement à la précédente, seulement si cette
précédente commande a fonctionné.
Voir code de retour.
;
: succession non conditionnéeChaque commande est exécuté l'une après l'autre même si l'une d'elle a mal fonctionné.
#!/bin/bash set -o posix printf "Un nouveau script utilisateur : son nom ? " { read nom && echo "#!/bin/bash" >> $nom && chmod u+x $nom && mv ~/$nom ~/MesScripts && /usr/bin/gedit ~/MesScripts/$nom ;}
En mettant&&
entre les commandes, ce script fonctionne aussi bien qu'avec les;
.
Mais avec&
, on obtiendrait un message d'erreur.
Dans cet exemple, la valeur d'une commande est nécessaire à la commande suivante.
On n'a pas chercher à rediriger le résultat d'une commande vers un fichier ou le contenu d'un fichier vers une commande (excepté pour concaténer dans le fichier créé la première ligne du futur script).
Pour le faire, il faut utiliser les redirections (voir plus bas).
On n'a pas cherché non plus à transmettre le résultat d'une commande
à une autre commande (tube|
)
Le shell bash fournit deux mécanismes pour regrouper les commandes:
Entre accolades, la valeur change commande après commande et le changement est conservé jusqu'à la dernière commande parce que toutes la série appartient au même processus.
#!/bin/bash { pwd ; cd ~/Documents ; echo $(pwd) ;}
/home/hypathie /home/hypathie/Documents
&
.#!/bin/bash { pwd ; cd ~/Documents ; echo $(pwd) ;} &
/home/hypathie
Le prompt ne revient pas il faut faire Ctrl+C !
L'utilisation du groupement de commandes sert souvent à la redirection globale de l'entrée du groupe de commande ou à sa sortie.
On le verra plus loin.
Les parenthèses sont des opérateurs.
Il n'y a donc pas besoin d'espace entre la parenthèse ouvrante et la première commande.
Insérée dans une parenthèse, la suite de commandes est exécutée dans un sous-shell.
#!/bin/bash nom=nenette (prenom=hypathie ; echo $prenom ) echo $nom
hypathie nenette
Voir : Guide avancé d'écriture des scripts Bash: 21. Sous-shells
Les variables comprises dans ces parenthèses, à l'intérieur du sous-shell, ne sont pas visibles par le reste du script. Le processus parent ou père ne peut pas accéder aux variables créées dans le processus fils, le sous-shell.
Dans le script ci-dessous, on voit que le terminal “reçoit le retour du shell père et celui du shell fils
( “echo $prenom”
).
#!/bin/bash nom=nenette ( prenom=hypathie ) echo $nom $prenom
nenette
Créer un sous-shell permet ainsi de protéger de ce qui se passe dans le processus fils.
Créer un processus fil permet aussi au processus père de continuer son programme “pendant” l'exécution du processus fils, ce qui évite de ralentir l'ensemble du programme.
iceweasel
avec :
iceweasel & [1] 4245
Ici[1]
est le jobID et4245
est le PID, l'identifiant du processus.
Pour aller plus loin voir la notion de processus et les commandes :ps
;top
;nice
etrenice
.
Dans le premier cas, si l'on ferme le terminal, on ferme aussi “iceweasel”,
processus fils du shell.
Mais dans le deuxième cas (en mettant&
après la commande) le processus fils est en arrière plan et l'on peut donc utiliser le shell, ou fermer le terminal sans tuer en même temps le processus fils (iceweasel).
Il est possible de lancer deux processus en parallèle. Comparez le retour des lignes n°2 et n°3 avec celles des lignes n°5 et n°6 du code ci-dessous.
#!/bin/bash ( echo "bonjour" ) & ( echo "au revoir" ) ( cd /etc/apt ; ls ) & ( cd /etc/calendar ; ls ) echo " " cd /etc/apt ; ls cd /etc/calendar ; ls
set --restricted
ou
set -r
On passe en mode restreint pour diminuer les risques.
En mode restreint, certaines commandes sont désactivées :
cd
exec
(commande qui permet des substitution de processus/
(pour éviter des modification à la racine)$PATH
: en le modifiant on peut changer l'utilisation de certaines commandes.$SHELL
: en le modifiant on peut utiliser un autre interpréteur, en cours de programme.$BASH_ENV
et $ENV
: les modifications de l'environnement ne se font pas sans connaissances.$SHELLOPTS
: où on peut changer les options d'environnement du shell
Les redirections permettent de travailler non pas en se servant du code de retour (qui indique la réussite ou l'échec de l'exécution d'une commande) mais sur les flux.
Un processus unix possède (par défaut) trois voies d'interaction entre le système et l'utilisateur. Une entrée et deux sorties. Chacun de ces “lieux” sont identifiés par un descripteur de fichier.
Pour chaque programme lancé, un flux est créé. Ce flux est une sorte de canal par lequel transite les données entre les espaces, entrée et sortie.
On peut imaginer un terminal, comme la réunion virtuelle d'un clavier et d'un écran.
Merci à captnfab pour cette comparaison sur IRC
<&- <&- # Permettent la fermeture de l'entrée standard et de la sortie standard. >| # Force une redirection vers un fichier.txt pour pouvoir écraser le fichier quand il existe et que l'option noclobber (-c) est activée.
ls vi 2>err # retour du prompt : le message d'erreur a été inscrit dans le fichier "erreurs" qui s'est créé s'il n'existait pas.
2>>fichier # si "fichier" n'existait pas le message d'erreur aurait été ajouté en dernière ligne.
2>/dev/null
(Tout ce qui y est dirigé est perdu, inutile de concaténer !) On s'en sert souvent lorsqu'on est intéressé par le fait de récupérer le code de retour.
>&
ls -l 1>&2 la sortie du répertoire courant et envoyé sur le canal de sortie d'erreur ; cela à pour effet, de lister le contenu, mais le terminal affiche alors le canal de sortie d'erreur. Relancer la dernière commande est impossible. On peut lancer une autre commande, ou faire ctrl+c. Oouffff
>>&
2>&1
Par exemple :
##vi: /usr/bin/vi ls vi 2>&1 2>erreurs # retour du prompt on retrouve le message d'erreurs dans le fichier "erreurs" qui s'est créé. Cela un équivalent de ls vi 2>err
ls vi erreur>errrrr 2>&1 #retour du prompt ls ne peut lister le fichier vi ; le message d'erreur est envoyé dans le fichier "errrr" qui est nouvellement créé et qui est la sortie standard (1), puis ls ne peut lister le fichier "erreur", le message est envoyé vers la sortie d'erreur qui est redirigé vers (1) c'est-à-dire le fichier "erreur".
Tout est là : le pipe
Écrire un script qui crée le dossier “ABCD” et 4 fichiers vides (nommés a b c d) ;
qui liste le contenu de “ABCD” et qui inscrit le résultat dans un fichier nommé “ls1” qui sera placé dans “ABCD” ;
qui depuis le répertoire personnel crée le fichier vide nommé “fichier.txt”,
liste à nouveau ABCD, inscrit le résultat dans le fichier “ls2”, rangé dans “ABCD”;
qui permet d'inscrire depuis le terminal une ligne de texte dans le fichier nommé “fichier.txt” ;
puis une deuxième ligne de texte dans “fichier.txt”, en affichant dans le terminal,
le nombre de lignes, de mots et d'octets que possède le fichier “fichier.txt” ;
se servir de différentes méthodes tout au long du script pour vérifier
au niveau du terminal que chaque commande s'est bien déroulée.
Bonne lecture
#!/bin/bash set -o posix { mkdir ~/ABCD 2>>/dev/null ;\ echo $? ;\ cd ABCD && touch a b c d ;\ echo $? ;\ ls -l >> ~/ABCD/ls1 ;\ echo $? ;\ cd ~ ;\ pwd ;\ touch ~/ABCD/fichier.txt ;\ echo $? ;\ pwd && ls -l ~/ABCD >> ~/ABCD/ls2 ;\ echo $? ;\ read phrase1 && echo ${phrase1} >> ~/ABCD/fichier.txt && echo $? ;\ read phrase2 ;\ cat >> ~/ABCD/fichier.txt << EOF $phrase2 EOF echo $? cat < ~/ABCD/fichier.txt | wc echo $? ;}