Vous n'êtes pas identifié(e).
L'icône rouge permet de télécharger chaque page du wiki visitée au format PDF et la grise au format ODT →
Ceci est une ancienne révision du document !
Nota : wiki n°4
Les autres numéros :
Contributeurs, les sont là pour vous aider, supprimez-les une fois le problème corrigé ou le champ rempli !
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 && ; || ) voir : état de sortie et code de retour).
Reprenons le script “scriptx”, et changeons les “;” d'abord par “&”, puis par “&&”
#!/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.
Pourquoi ?
(Dans l'exemple ci-dessus, chaque commande étant traitée par un sous-shell, la valeur d'une commande ne peut pas être conservée dans un même processus pour que chaque commande puisse “travailler en rapport au RESULTAT 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.)
le shell bash fournit deux mécanismes pour regrouper les commandes; l'insertion de la suite de commandes entre accolades et l'insertion de cette suite de commandes entre une paire de parenthèses.
Les accolades sont des mots-clé de bash.
Il ne faut donc pas oublier de mettre un espace entre l'accolade ouvrante et la première commande de la liste.
Entre accolades, la valeur change commandes après commande ; le changement est conservé jusqu'à la dernière commande parce que toutes les modifications sont faites dans le shell courant.
#!/bin/bash { pwd ; cd ~/Documents ; echo $(pwd) ;}
Retour :
/home/hypathie /home/hypathie/Documents
#!/bin/bash { pwd ; cd ~/Documents ; echo $(pwd) ;} &
retour :
/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
Retour :
hypathie nenette
Voir : Guide avancé d'écriture des scripts Bash: 21. Sous-shells
#!/bin/bash { var1=yep ;} echo $var1 var3=coucou { var4=yep ; $var4 ;} echo $var3
retour :
yep essai.sh: ligne5: yep : commande introuvable coucou
Mais :
#!/bin/bash var1=coucou (var2=yep ) echo $var1 $var2 ( var3="au revoir" ; echo $var3 )
retour :
coucou au revoir
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, le script, ne peut pas lire les variables créées dans le processus fils, le sous-shell.
Dans le script ci-dessus 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
Retour :
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 : ça évite de ralentir l'ensemble du programme.
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 :
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".
É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 $? ;}
Tout est là : le pipe