Qu'est-ce qui rend un caractère spécial ? S'il a une signification en dehors de la signification littérale, une meta signification, alors nous lui donnons le nom de caractère spécial.
Caractères spéciaux se trouvant dans les scripts et ailleurs
Commentaires. Les lignes commençant avec un # (à l'exception de #!) sont des commentaires et ne seront pas exécutées.
# Cette ligne est un commentaire.
Les commentaires peuvent apparaître après la fin d'une commande.
echo "Un commentaire va suivre." # Un commentaire ici. # ^ Notez l'espace devant le #
Les commentaires peuvent aussi suivre un blanc au début d'une ligne.
# Une tabulation précède ce commentaire.
On peut même inclure les commentaires à l'intérieur d'un pipe.
initial=( `cat "$startfile" | sed -e '/#/d' | tr -d '\n' |\ # Supprimer les caractères '#' de commentaire. sed -e 's/\./\. /g' -e 's/_/_ /g'` ) # Extrait du script life.sh
Un commentaire ne peut pas être suivi d'une commande sur la même ligne. Il n'existe pas de façon de terminer le commentaire pour que le « vrai code » commence sur la même ligne. Utilisez une nouvelle ligne pour la commande suivante.
Bien sûr, un guillemet ou un # échappé dans une instruction echo ne commence pas un commentaire. De la même manière, un # apparaît dans certaines expressions avec substitution de paramètres et dans les expressions numériques constantes.
echo "Le # ici ne commence pas un commentaire." echo 'Le # ici ne commence pas un commentaire.' echo Le \# ici ne commence pas un commentaire. echo Le # ici commence un commentaire. echo ${PATH#*:} # Substitution de paramètres, pas un commentaire. echo $(( 2#101011 )) # Conversion de base, pas un commentaire. # Merci à S.C.
Les caractères standards de guillemet et d'échappement (" ' \) échappent le #.
Certaines opérations de filtrage de motif font aussi appel au #.
Séparateur de commande [point-virgule]. Permet de placer deux commandes ou plus sur la même ligne.
echo bonjour; echo ici if [ -x "$nomfichier" ]; then # Notez que "if" et "then" doivent être séparés # par une espace. Pourquoi ? echo "Le fichier $nomfichier existe."; cp $nomfichier $nomfichier.sauve else echo "Le fichier $nomfichier est introuvable."; touch $nomfichier fi; echo "Test du fichier terminé."
Notez que le « ; » a parfois besoin d'être échappé.
Fin de ligne dans une sélection par cas case [double point-virgule].
case "$variable" in abc) echo "\$variable = abc" ;; xyz) echo "\$variable = xyz" ;; esac
Terminators in a case option (version 4+ of Bash).
Commande « point » [point]. Équivalent au source (voir l'Exemple 15.22, « « Inclure » un fichier de données »). C'est une commande intégrée de Bash.
« point », comme composant d'un nom de fichier. Lors de l'utilisation de noms de fichiers, un point au début est le préfixe d'un fichier « caché », un fichier que ls ne montre habituellement pas.
bash$ touch .fichier_caché bash$ ls -l total 10 -rw-r--r-- 1 bozo bozo 4034 Jul 18 22:04 donnée1.carnet_d_adresses -rw-r--r-- 1 bozo bozo 4602 May 25 13:58 donnée1.carnet_d_adresses.bak -rw-r--r-- 1 bozo bozo 877 Dec 17 2000 boulot.carnet_d_adresse bash$ ls -al total 14 drwxrwxr-x 2 bozo bozo 1024 Aug 29 20:54 ./ drwx------ 52 bozo bozo 3072 Aug 29 20:51 ../ -rw-r--r-- 1 bozo bozo 4034 Jul 18 22:04 donnée1.carnet_d_adresses -rw-r--r-- 1 bozo bozo 4602 May 25 13:58 donnée1.carnet_d_adresses.bak -rw-r--r-- 1 bozo bozo 877 Dec 17 2000 boulot.carnet_d_adresse -rw-rw-r-- 1 bozo bozo 0 Aug 29 20:54 .fichier_caché
Au sujet des noms de répertoires, un seul point représente le répertoire courant et deux points à la suite indiquent le répertoire parent.
bash$ pwd /home/bozo/projets bash$ cd . bash$ pwd /home/bozo/projets bash$ cd .. bash$ pwd /home/bozo/
Le point apparaît souvent comme répertoire de destination d'une commande de mouvement de fichiers. Dans ce contexte, cela signifie le répertoire courant..
bash$ cp /home/bozo/travail_en_cours/débarras/* .
Copiez tous les fichiers du répertoire « débarras » dans $PWD.
Filtrage d'un caractère par le « point ». Pour le filtrage de caractères au sein d'une expression rationnelle, un « point » correspond à un seul caractère.
Citation partielle [guillemet double]. "CHAÎNE" empêche l'interprétation de la plupart des caractères spéciaux présents dans la CHAÎNE. Voir le Chapitre 5, Guillemets et apostrophes.
Citation totale [guillemet simple]. 'CHAÎNE' empêche l'interprétation de tous les caractères spéciaux présents dans la CHAÎNE. Ces guillemets sont plus puissants que "CHAÎNE". Voir aussi le Chapitre 5, Guillemets et apostrophes.
Opérateur virgule. L'opérateur virgule [15] relie une suite d'opérations arithmétiques. Toutes sont évaluées, mais seul le résultat de la dernière est renvoyé.
let "t2 = ((a = 9, 15 / 3))" # Initialise "a = 9" et "t2 = 15 / 3".
The comma operator can also concatenate strings.
for file in /{,usr/}bin/*calc # ^ Find all executable files ending in "calc" #+ in /bin and /usr/bin directories. do if [ -x "$file" ] then echo $file fi done # /bin/ipcalc # /usr/bin/kcalc # /usr/bin/oidcalc # /usr/bin/oocalc # Thank you, Rory Winston, for pointing this out.
Lowercase conversion in parameter substitution (added in version 4 of Bash).
Échappement [antislash]. Un mécanisme d'échappement pour les caractères seuls.
\X échappe le caractère X. Cela a pour effet de « mettre X entre guillemets », et est équivalent à 'X'. Le \ peut être utilisé pour mettre " et ' entre guillemets, ce qui permet de les écrire sous forme littérale.
Voir le Chapitre 5, Guillemets et apostrophes pour une explication plus détaillée des caractères échappés.
Séparateur dans le chemin d'un fichier [barre oblique]. Sépare les composants d'un nom de fichier (comme dans /home/bozo/projets/Makefile).
C'est aussi l'opérateur arithmétique de division.
Substitution de commandes [guillemet inversé]. L'expression `commande` rend la sortie de commande disponible pour l'affecter à une variable. On parle de guillemets inversés.
Commande null [deux-points]. C'est l'équivalent shell d'un « NOP » (no op, c'est-à-dire « pas d'opération »). Elle peut être considérée comme un synomyme pour la commande intégrée true. La commande « : » est elle-même une commande intégrée Bash et son état de sortie est true (0).
: echo $? # 0
Boucle sans fin :
while : do operation-1 operation-2 ... operation-n done # Identique à : # while true # do # ... # done
Sert de bouche-trou dans un test if/then :
if condition then : # Ne rien faire et continuer else # Et sinon... faire_quelque_chose fi
Sert de bouche-trou quand on attend une opération binaire, voir l'Exemple 8.2, « Utiliser des opérations arithmétiques » et les paramètres par défaut.
: ${nom_utilisateur=`whoami`} # ${nom_utilisateur=`whoami`} donne une erreur sans les deux-points en tout début # sauf si "nom_utilisateur" est une commande, intégrée ou non...
Sert de bouche-trou quand on attend une commande dans un document en ligne. Voir l'Exemple 19.10, « document intégré « anonyme » ».
Évalue une suite de variables en utilisant la substitution de paramètres (comme dans l'Exemple 10.7, « Utiliser la substitution et les messages d'erreur »).
: ${HOSTNAME?} ${USER?} ${MAIL?} # Affiche un message d'erreur #+ si une variable d'environnement (ou plusieurs) n'est pas initialisée.
Expansion de variable / remplacement d'une sous-chaîne.
En combinaison avec l'opérateur de redirection >, tronque un fichier à la taille zéro sans modifier ses droits. Crée le fichier s'il n'existait pas auparavant.
: > données.xxx # Fichier "données.xxx" maintenant vide # Même effet que cat /dev/null >données.xxx # Néanmoins, cela ne crée pas un nouveau processus, car ":" est une commande intégrée.
Voir aussi l'Exemple 16.15, « Utiliser tail pour surveiller le journal des traces système ».
En combinaison avec l'opérateur de redirection >>, elle n'a pas d'effet sur un fichier cible déjà existant (: >> nouveau_fichier). Crée le fichier s'il n'existait pas.
Peut servir à commencer une ligne de commentaire bien que ce ne soit pas recommandé. Utiliser # pour un commentaire désactive la vérification d'erreur pour le reste de la ligne, donc vous pouvez y mettre pratiquement n'importe quoi. En revanche, ce n'est pas le cas avec :.
: Ceci est un commentaire qui génère une erreur, ( if [ $x -eq 3] ).
Le « : » sert de séparateur de champ, dans /etc/passwd et dans la variable $PATH.
bash$ echo $PATH /usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/sbin:/usr/sbin:/usr/games
Les deux-points sont acceptables comme nom de fonction.
:() { echo "Le nom de cette fonction est \":\" " } : # Le nom de cette fonction est ":"
Ce comportement n'est pas portable, et par conséquent nous ne le recommandons pas.
Inverse le sens d'un test ou d'un état de sortie. L'opérateur ! inverse l'état de sortie de la commande à laquelle il est appliqué (voir l'Exemple 6.2, « Inverser une condition en utilisant ! »). Il inverse aussi la signification d'un opérateur de test. Par exemple, cela peut changer le sens d'un égal (=) en un différent ( != ). L'opérateur ! est un mot-clé Bash.
Dans un autre contexte, le ! apparaît aussi dans les références indirectes de variable.
Dans un contexte encore différent, à partir de la ligne de commande, le ! appelle le mécanisme d'historique de Bash (voir l'Annexe K, Commandes d'historique). Notez que ce mécanisme est désactivé dans les scripts.
Joker [astérisque]. Le caractère * sert de « joker » pour l'expansion des noms de fichiers dans les remplacements. Utilisé seul, il correspond à tous les noms de fichier d'un répertoire donné.
bash$ echo * abs-book.sgml add-drive.sh agram.sh alias.sh
L'astérisque * représente tout caractère répété plusieurs fois (ou zéro) dans une expression rationnelle.
Opérateur arithmétique. Dans le contexte des opérations arithmétiques, * indique la multiplication.
**Le double astérisque ** représente soit l'opérateur exponentiel, soit un remplacement étendu de noms de fichiers.
Opérateur de test. À l'intérieur de certaines expressions, le ? indique un test pour une condition.
Dans une expression entre doubles parenthèses, ? peut servir comme élément d'un opérateur ternaire dans le style du langage C, ?:.
condition?resultat-si-condition-vraie:resultat-si-condition-fausse
(( var0 = var1<98?9:21 )) # ^ ^ # if [ "$var1" -lt 98 ] # then # var0=9 # else # var0=21 # fi
Dans une expression de substitution de paramètres, le ? teste si une variable a été initialisée.
Joker. Le caractère ? sert de joker pour un seul caractère dans l'expansion d'un nom de fichier dans un remplacement, et représente également un caractère dans une expression rationnelle étendue.
Substitution de variable (contenu d'une variable).
var1=5 var2=23skidoo echo $var1 # 5 echo $var2 # 23skidoo
Un $ préfixant un nom de variable donne la valeur que contient cette variable.
Fin de ligne. Dans une expression rationnelle, un $ signifie la fin d'une ligne de texte.
Quoted string expansion. This construct expands single or multiple escaped octal or hex values into ASCII [16] or Unicode characters.
Variable contenant l'état de sortie. La variable $? contient l'état de sortie d'une commande, d'une fonction ou d'un script.
Variable contenant l'identifiant du processus. La variable $$ contient le PID [17] du script dans lequel elle apparaît.
Groupe de commandes.
(a=bonjour; echo $a)
Une liste de commandes entre parenthèses lance un sous-shell.
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.
a=123 ( a=321; ) echo "a = $a" # a = 123 # "a" à l'intérieur des parenthèses agit comme une variable locale.
Tableau=(element1 element2 element3)>
echo \"{Mots,entourés,de,guillemets}\" # " prefixe et " suffixe # "Mots" "entourés" "de" "guillemets" cat {fichier1,fichier2,fichier3} > fichier_combiné # Concatène les fichiers fichier1, fichier2 et fichier3 vers fichier_combiné. cp fichier22.{txt,sauve} # Copie "fichier22.txt" dans "fichier22.sauve" </formalpara> <para>Une commande peut agir sur une liste de fichiers séparés par des virgules entre des <replaceable>accolades</replaceable> <footnote> <para>Le shell fait l'<firstterm>expansion des accolades</firstterm>. La commande elle-même agit sur le <emphasis>résultat</emphasis> de cette expansion. </para> </footnote>. L'expansion de noms de fichiers (<link linkend="globbingref">remplacement</link>) s'applique aux fichiers contenus dans les accolades.</para> <caution> <para>Aucune espace n'est autorisée à l'intérieur des accolades <emphasis>sauf si</emphasis> les espaces sont comprises dans des guillemets ou échappés.</para> <para><userinput>echo {fichier1,fichier2}\ :{\ A," B",' C'}</userinput></para> <para><computeroutput>fichier1 : A fichier1 : B fichier1 : C fichier2 : A fichier2 : B fichier2 : C</computeroutput></para> </caution> </listitem> </varlistentry> <varlistentry> <term><anchor id="braceexpref33"/><token>{a..z}</token></term> <listitem> <indexterm> <primary>{a..z}</primary> </indexterm> <indexterm> <primary>caractère spécial</primary> <secondary>{}</secondary> </indexterm> <indexterm> <primary>Expansion étendue d'accolades</primary> </indexterm> <formalpara> <title>Expansion étendue d'accolades</title> <para> <programlisting><![CDATA[echo {a..z} # a b c d e f g h i j k l m n o p q r s t u v w x y z # Affiche les caractères entre a et z. echo {0..3} # 0 1 2 3 # Affiche les caractères entre 0 et 3. base64_charset=( {A..Z} {a..z} {0..9} + / = ) DIFF63 # Initializing an array, using extended brace expansion. # From vladz's "base64.sh" example script.
L'expression {a..z}, avec expansion étendue d'accolades est une fonctionnalité introduite dans la version 3 de Bash.
Bloc de code [accolade]. On dit aussi groupe en ligne. Cette expression crée une fonction anonyme (une fonction sans nom). Néanmoins, contrairement à une fonction standard, les variables d'un bloc de code restent visibles par le reste du script.
bash$ { local a; a=123; } bash: local: can only be used in a function
a=123 { a=321; } echo "a = $a" # a = 321 (valeur à l'intérieur du bloc de code) # Merci à S.C.
Le bloc de code entouré par des accolades peut utiliser la redirection d'entrées/sorties.
Exemple 3.1. Blocs de code et redirection d'entrées/sorties
#!/bin/bash # Lit les lignes de /etc/fstab. Fichier=/etc/fstab { read ligne1 read ligne2 } < $Fichier echo "La première ligne dans $Fichier est :" echo "$ligne1" echo echo "La deuxième ligne dans $Fichier est :" echo "$ligne2" exit 0 # Maintenant, comment analysez-vous les champs séparés de chaque ligne ? # Astuce : utilisez awk, ou... # ... Hans-Joerg Diers suggère d'utiliser la commande set de Bash.
Contrairement à un groupe de commandes entre parenthèses, comme ci-dessus, un bloc de code entouré par des accolades ne sera pas lancé dans un sous-shell. [18]
Emplacement pour du texte. Utilisé après xargs -i (option de replacement de chaîne). Les doubles accolades {} sont un emplacement pour du texte en sortie.
ls . | xargs -i -t cp ./{} $1 # ^^ ^^ # Provient de l'exemple "ex42.sh" (copydir.sh).
Chemin. Principalement utilisé pour les commandes find. Ce n'est pas une commande intégrée du shell.
Le « ; » termine l'option -exec d'une séquence de commandes find. Il a besoin d'être échappé pour que le shell ne l'interprète pas.
Teste l'expression entre [ ]. Notez que [ fait partie de la commande intégrée test (et en est un synonyme), ce n'est pas un lien vers la commande externe /usr/bin/test.
Test.
Teste l'expression entre [[ ]]. C'est un mot-clé du shell.
Voir les explications sur la structure [[ ... ]].
Élément d'un tableau.
Accolés au nom d'un tableau, les crochets indiquent l'indice d'un élément.
Tableau[1]=slot_1 echo ${Tableau[1]}
Ensemble de caractères.
Dans une expression rationnelle, les crochets désignent un ensemble de caractères devant servir de motif (N.d.T : cet ensemble peut être un intervalle).
expansion d'entiers.
Évalue l'expression entière entre $[ ].
a=3 b=7 echo $[$a+$b] # 10 echo $[$a*$b] # 21
Note that this usage is deprecated, and has been replaced by the (( ... )) construct.
Expansion d'entiers.
Développe et évalue une expression entière entre (( )).
Voir les explications sur la structure (( ... )).
nom_script >nom_fichier redirige la sortie de nom_script vers le fichier nom_fichier et écrase nom_fichier s'il existe déjà.
commande &>nom_fichier redirige à la fois stdout et stderr de commande vers nom_fichier.
This is useful for suppressing output when testing for a condition. For example, let us test whether a certain command exists.
bash$ type bogus_command &>/dev/null bash$ echo $? 1
Or in a script:
command_test () { type "$1" &>/dev/null; } # ^ cmd=rmdir # Legitimate command. command_test $cmd; echo $? # 0 cmd=bogus_command # Illegitimate command command_test $cmd; echo $? # 1
commande >&2 redirige stdout de commande vers stderr.
nom_script >>nom_fichier ajoute la sortie de nom_script à la fin du fichier nom_fichier. Si le fichier n'existe pas déjà, il est créé.
[i]<>nom_fichier ouvre le fichier nom_fichier en lecture et écriture, et lui affecte le descripteur de fichier i. Si nom_fichier n'existe pas, il est créé.
(commande)>
<(commande)
Dans un autre contexte, les caractères < et > agissent comme des opérateurs de comparaison de chaînes de caractères.
Dans un contexte encore différent, les caractères < et > agissent comme des opérateurs de comparaison d'entiers. Voir aussi l'Exemple 16.9, « Utiliser expr ».
Redirection utilisée dans un document en ligne.
Redirection utilisée dans une chaîne en ligne.
leg1=carottes leg2=tomates if [[ "$leg1" < "$leg2" ]] then echo -n "Le fait que $leg1 précède $leg2 dans le dictionnaire " echo "n'a rien à voir avec mes préférences culinaires." else echo "Mais quel type de dictionnaire utilisez-vous?" fi
Délimitation d'un mot dans une expression rationnelle.
bash$ grep '\<mot\>' fichier_texte
Tube. Passe la sortie (stdout) de la commande précédente à l'entrée (stdin) de la suivante ou au shell. Cette méthode permet de chaîner les commandes ensemble.
echo ls -l | sh # Passe la sortie de "echo ls -l" au shell #+ avec le même résultat qu'un simple "ls -l". cat *.lst | sort | uniq # Assemble et trie tous les fichiers ".lst", puis supprime les lignes #+ dupliquées.
La sortie d'une ou plusieurs commandes peut être envoyée à un script via un tube.
#!/bin/bash # uppercase.sh : Change l'entrée en majuscules. tr 'a-z' 'A-Z' # La plage de lettres doit être entre guillemets pour empêcher que la #+ génération des noms de fichiers ne se fasse que sur les fichiers à un #+ caractère. exit 0
Maintenant, envoyons par le tube la sortie de ls -l à ce script.
bash$ ls -l | ./uppercase.sh -RW-RW-R-- 1 BOZO BOZO 109 APR 7 19:49 1.TXT -RW-RW-R-- 1 BOZO BOZO 109 APR 14 16:48 2.TXT -RW-R--R-- 1 BOZO BOZO 725 APR 20 20:56 FICHIER-DONNEES
Le canal stdout de chaque processus dans un tube doit être lu comme canal stdin par le suivant. Si ce n'est pas le cas, le flux de données va se bloquer et le tube ne se comportera pas comme il devrait.
cat fichier1 fichier2 | ls -l | sort # La sortie à partir de "cat fichier1 fichier2" disparaît.
Un tube tourne en tant que processus fils et ne peut donc modifier les variables du script.
variable="valeur_initiale" echo "nouvelle_valeur" | read variable echo "variable = $variable" # variable = valeur_initiale
Si une des commandes du tube échoue, l'exécution du tube se termine prématurément. Dans ces conditions, on a un tube cassé et on envoie un signal SIGPIPE.
Force une redirection (même si l' option noclobber est activée). Ceci va forcer l'écrasement d'un fichier déjà existant.
Opérateur logique OU. Dans une structure de test , l'opérateur || a comme valeur de retour 0 (succès) si l'une des conditions est vraie.
Exécuter la tâche en arrière-plan. Une commande suivie par un & fonctionnera en tâche de fond.
bash$ sleep 10 & [1] 850 [1]+ Done sleep 10
À l'intérieur d'un script, les commandes et même les boucles peuvent tourner en tâche de fond.
Exemple 3.3. Exécuter une boucle en tâche de fond
#!/bin/bash # background-loop.sh for i in 1 2 3 4 5 6 7 8 9 10 # Première boucle. do echo -n "$i " done & # Exécute cette boucle en tâche de fond. # S'exécutera quelques fois après la deuxième boucle. echo # Ce 'echo' ne s'affichera pas toujours. for i in 11 12 13 14 15 16 17 18 19 20 # Deuxième boucle. do echo -n "$i " done echo # Ce 'echo' ne s'affichera pas toujours. # ====================================================== # La sortie attendue de ce script : # 1 2 3 4 5 6 7 8 9 10 # 11 12 13 14 15 16 17 18 19 20 # Mais, quelque fois, vous obtenez : # 11 12 13 14 15 16 17 18 19 20 # 1 2 3 4 5 6 7 8 9 10 bozo $ # (Le deuxième 'echo' ne s'exécute pas. Pourquoi ?) # Occasionnellement aussi : # 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # (Le premier 'echo' ne s'exécute pas. Pourquoi ?) # Et très rarement : # 11 12 13 1 2 3 4 5 6 7 8 9 10 14 15 16 17 18 19 20 # La boucle en avant plan s'exécute avant celle en tâche de fond. exit 0 # Nasimuddin Ansari suggère d'ajouter sleep 1 #+ après le echo -n "$i" aux lignes 6 et 14, #+ pour un peu d'amusement.
Une commande exécutée en tâche de fond à l'intérieur d'un script peut faire se suspendre l'exécution, attendant l'appui sur une touche. Heureusement, il est possible d'y remédier.
Opérateur logique ET. Dans une structure de test, l'opérateur && renvoie 0 (succès) si et seulement si les deux conditions sont vraies.
Option, préfixe. Introduit les options pour les commandes ou les filtres. Sert aussi de préfixe pour un opérateur. Préfixe pour un paramètre par défaut dans la substitution de paramètres.
COMMANDE -[Option1][Option2][...]
ls -al
sort -dfu $nom_fichier
if [ $fichier1 -ot $fichier2 ] then # ^ echo "Le fichier $fichier1 est plus ancien que le $fichier2." fi if [ "$a" -eq "$b" ] then # ^ echo "$a est égal à $b." fi if [ "$c" -eq 24 -a "$d" -eq 47 ] then # ^ ^ echo "$c vaut 24 et $d vaut 47." fi param2=${param1:-$DEFAULTVAL} #
--
Le tiret double -- est le préfixe des options longues pour les commandes.
sort --ignore-leading-blanks
Utilisé avec une commande interne Bash, il signifie la fin des options de cette commande spécifique.
Ceci donne un moyen simple pour supprimer les fichiers dont les noms commencent avec un tiret.
bash$ ls -l -rw-r--r-- 1 bozo bozo 0 Nov 25 12:29 -vilainnom bash$ rm -- -vilainnom bash$ ls -l total 0
Le double-tiret est aussi utilisé avec set.
set -- $variable (comme dans Exemple 15.18, « Réaffecter les paramètres de position »)
Redirection à partir de ou vers stdin ou stdout [tiret].
bash$ cat - abc abc ... Ctl-D
Comme attendu, cat - lit sur stdin, dans ce cas la saisie de l'utilisateur au clavier, et envoie vers stdout. Mais, est-ce que la redirection des entrées/sorties utilisant - ont une application réelle ?
(cd /source/répertoire && tar cf - . ) | (cd /dest/répertoire && tar xpvf -) # Déplace l'ensemble des fichiers d'un répertoire vers un autre # [reproduit ici avec la permission d'Alan Cox <a.cox@swansea.ac.uk>, légèrement modifié] # 1) cd /source/répertoire # Répertoire source, où se trouvent les fichiers à déplacer. # 2) && # "liste ET": si l'opération 'cd' a fonctionné, # alors il exécute la commande suivante. # 3) tar cf - . # L'option 'c' de la commande d'archivage 'tar' crée une nouvelle archive, # l'option 'f' (fichier), suivie par '-' désigne stdout comme fichier cible. # et place l'archive dans le répertoire courant ('.'). # 4) | # Tube... # 5) ( ... ) # Un sous-shell. # 6) cd /dest/répertoire # Se déplace dans le répertoire de destination. # 7) && # "liste ET", comme ci-dessus. # 8) tar xpvf - # Déballe l'archive ('x'), préserve l'appartenance # et les droits des fichiers ('p'), # puis envoie de nombreux messages vers stdout ('v'), # en lisant les données provenant de stdin # ('f' suivi par un '-'). # # Notez que 'x' est une commande, et 'p', 'v', 'f' # sont des options. # Ouf ! # Plus élégant, mais équivalent à : # cd /source/répertoire # tar cf - . | (cd ../dest/répertoire; tar xpvf -) # # A aussi le même effet : # cp -a /source/répertoire/* /dest/répertoire # Ou : # cp -a /source/répertoire/* /source/répertoire/.[^.]* /dest/répertoire # S'il y a des fichiers cachés dans /source/répertoire.
bunzip2 -c linux-2.6.16.tar.bz2 | tar xvf - # --décompresse l'archive-- | --puis la passe à "tar"-- # Si "tar" n'a pas intégré le correctif de support de "bunzip2", #+ il faut procéder en deux étapes distinctes avec un tube. # Le but de cet exercice est de désarchiver les sources du noyau compressées #+ avec bzip2.
Notez que dans ce contexte le signe « - » n'est pas en lui-même un opérateur Bash, mais plutôt une option reconnue par certains utilitaires UNIX qui écrivent dans stdout ou lisent dans stdin, tels que tar, cat, etc.
bash$ echo "quelquechose" | cat - quelquechose
Lorsqu'un nom de fichier est attendu, un - redirige la sortie vers stdout (vous pouvez le rencontrer avec tar cf), ou accepte une entrée de stdin, plutôt que d'un fichier. Cett méthode utilise un outil principalement destiné à manipuler des fichiers comme filtre dans un tube.
bash$ file Usage: file [-bciknvzL] [-f namefile] [-m magicfiles] file...
Tout seul sur une ligne de commande, file échoue avec un message d'erreur.
Ajoutez un « - » pour pouvoir vous en servir. Le shell attend alors une entrée de l'utilisateur.
bash$ file - abc standard input: ASCII text bash$ file - #!/bin/bash standard input: Bourne-Again shell script text executable
Maintenant, la commande accepte une entrée de stdin et l'analyse.
Le « - » peut être utilisé pour envoyer stdout à d'autres commandes via un tube, ce qui permet quelques astuces comme l'ajout de lignes au début d'un fichier.
Par exemple, vous pouvez utiliser diff pour comparer un fichier avec une partie d'un autre fichier :
grep Linux fichier1 | diff fichier2 -
Finalement, un exemple réel utilisant - avec tar.
Les noms de fichiers commençant avec un « - » peuvent poser problème lorsqu'ils sont couplés avec l'opérateur de redirection « - ». Votre script doit détecter de tels fichiers et leur ajouter un préfixe approprié, par exemple ./-NOMFICHIER, $PWD/-NOMFICHIER, ou $NOMCHEMIN/-NOMFICHIER.
Il y aura probablement un problème si la valeur x d'une variable commence avec un -.
var="-n" echo $var # A le même effet qu'un "echo -n" et donc n'affiche rien.
Répertoire précédent. cd - revient au répertoire précédent en utilisant la variable d'environnement $OLDPWD.
Ne confondez pas « - » utilisé dans ce sens avec l'opérateur de redirection « - » vu précédemment. L'interprétation du « - » dépend du contexte dans lequel il apparaît.
Moins. Le signe moins indique l'opération arithmétique.
Égal. Opérateur d'affectation.
a=28 echo $a # 28
Dans un autre contexte, le signe = est un opérateur de comparaison de chaînes de caractères.
Plus. Opérateur arithmétique d'addition.
Dans un autre contexte, le + est un opérateur d'expression rationnelle.
Option. Option pour une commande ou un filtre.
Certaines commandes, intégrées ou non, utilisent le + pour activer certaines options et le - pour les désactiver. Dans la substitution de paramètres, le + préfixe une autre valeur qu'une variable étend.
Modulo. Opérateur arithmétique modulo (reste d'une division entière).
let "z = 5 % 3" echo $z # 2
Dans un autre contexte, le % est un opérateur de reconnaissance de motifs.
Répertoire de l'utilisateur [tilde]. Le ~ correspond à la variable interne $HOME. ~bozo est le répertoire de l'utilisateur bozo et ls ~bozo liste son contenu. ~/ est le répertoire de l'utilisateur courant et ls ~/ liste son contenu.
bash$ echo ~bozo /home/bozo bash$ echo ~ /home/bozo bash$ echo ~/ /home/bozo/ bash$ echo ~: /home/bozo: bash$ echo ~utilisateur-inexistant ~utilisateur-inexistant
Répertoire courant. Correspond à la variable interne $PWD.
Répertoire courant précédent. Correspond à la variable interne $OLDPWD.
correspondance d'une expression rationnelle. Cet opérateur a été introduit avec la version 3 de Bash.
Début de ligne. Dans une expression rationnelle, un « ^ » correspond au début d'une ligne de texte.
Conversion en majuscules dans la substitution de paramètres (ajout de la version 4 de Bash).
Modifient le comportement d'un terminal ou de l'affichage d'un texte. Un caractère de contrôle est une combinaison CONTROL + touche (appuyés simultanément). Un caractère de contrôle peut aussi être écrit en notation octal ou hexadécimal, après un échappement.
Les caractères de contrôle ne sont normalement pas utiles à l'intérieur d'un script.
Ctl-A
Déplace le curseur au début de la ligne de texte (sur la ligne de commande).
Ctrl-B
Retour en arrière (backspace) non destructif.
Ctrl-C
Termine un job en avant-plan.
Se déconnecte du shell (similaire à un exit).
C'est le caractère EOF (End Of File, fin de fichier), qui termine aussi l'entrée de stdin.
Lors de la saisie de texte sur la console ou dans une fenêtre xterm, Ctl-D efface le caractère sous le curseur. Quand aucun caractère n'est présent, Ctl-D vous déconnecte de la session. Dans un terminal graphique, ceci a pour effet de fermer la fenêtre.
Ctl-E
Moves cursor to end of line of text (on the command-line).
Ctl-F
Moves cursor forward one character position (on the command-line).
CLOCHE (bip). Sur quelques anciens terminaux comme les télétypes, ceci fera vraiment sonner une cloche. Dans un xterm, cela pourrait sonner.
Ctrl-H
Supprime le caractère précédent (Backspace). Efface les caractères sur lequel le curseur passe en arrière.
#!/bin/bash # Intègre Ctrl-H dans une chaîne de caractères. a="^H^H" # Deux Ctrl-H (backspaces) # Ctrl-V Ctrl-H si vous utilisez vi/vim echo "abcdefg" # abcdefg echo echo -n "abcdefg$a " # abcd fg # Espace à la fin ^ ^ Deux fois backspaces. echo echo -n "abcdef$a" # abcdef # Pas d'espace à la fin ^ Ne fait pas de backspace (pourquoi?). # Les résultats pourraient ne pas être ceux attendus. echo; echo # Constantin Hagemeier suggère d'essayer : # a=$'\010\010' # a=$'\b\b' # a=$'\x08\x08' # mais cela ne modifie pas les résultats.
Ctrl-I
Tabulation horizontale.
Saut à la ligne (line feed). Dans un script, cela pourrait aussi s'exprimer en notation octale -- '\012' ou en notation hexadécimal -- '\x0a'.
Ctrl-K
Tabulation verticale.
Lors de la saisie de texte sur la console ou dans une fenêtre xterm, Ctl-K efface les caractères en commençant à partir du curseur jusqu'à la fin de la ligne. Within a script, Ctl-K may behave differently, as in Lee Lee Maschmeyer's example, below.
Ctrl-L
Formfeed (efface l'écran du terminal). Dans un terminal, ceci a le même effet que la commande clear. Une fois envoyé à une imprimante, un Ctl-L éjecte la page de papier.
Ctrl-M
Retour chariot.
#!/bin/bash # Merci à Lee Maschmeyer pour cet exemple. read -n 1 -s -p \ $'Control-M place le curseur au début de cette ligne. Tapez sur Enter. \x0d' # Bien sûr, '0d' est l'équivalent en #+ hexadécimal de Control-M. echo >&2 # Le '-s' rend la frappe invisible, donc il est nécessaire d'aller #+ explicitement sur la nouvelle ligne. read -n 1 -s -p $'Control-J place le curseur sur la ligne suivante. \x0a' # '0a' est l'équivalent hexadécimal de Control-J, le retour chariot. echo >&2 ### read -n 1 -s -p $'Et Control-K\x0bva en bas.' echo >&2 # Control-K est la tabulation verticale. # Un meilleur exemple de l'effet d'une tabulation verticale est : var=$'\x0aCeci est la ligne du bas\x0bCeci est la ligne du haut\x0a' echo "$var" # Ceci fonctionne de la même façon que l'exemple ci-dessus. Néanmoins : echo "$var" | col # Ceci fait que la fin de ligne droite est plus haute que la gauche. # Ceci explique pourquoi nous avons commencé et terminé avec un retour chariot, #+ pour éviter un écran déséquilibré. # Comme l'explique Lee Maschmeyer : # -------------------------- # Dans le [premier exemple de tabulation verticale]... la tabulation verticale #+ fait que l'affichage va simplement en-dessous sans retour chariot. # Ceci est vrai seulement sur les périphériques, comme la console Linux, qui ne #+ peuvent pas aller "en arrière". # Le vrai but de VT est d'aller directement en haut, et non pas en bas. # Cela peut être utilisé sur une imprimante. # L'utilitaire col peut être utilisé pour émuler le vrai comportement de VT. exit 0
Ctl-N
Supprime une ligne de texte rappelée à partir du tampon de l'historique [20] (sur la ligne de commande).
Ctl-O
Lance un retour à la ligne (sur la ligne de commande).
Ctl-P
Rappelle la dernière commande à partir du tampon historique (sur la ligne de commande).
Ctrl-Q
Sort du mode pause du terminal (XON).
Ceci réactive le stdin du terminal après qu'il ait été mis en pause.
Ctl-R
Recherche arrière pour le texte dans le tampon historique (sur la ligne de commande).
Ctrl-S
Pause du terminal (XOFF).
Ceci gèle le stdin du terminal (utilisez Ctrl-Q pour en sortir).
Ctrl-T
Inverse la position du caractère sous le curseur avec celle du caractère précédent (sur la ligne de commande).
Ctrl-U
Efface une ligne de l'entrée depuis le début de la ligne jusqu'à la position du curseur. Avec certains paramétrages, Ctrl-U efface la ligne d'entrée entière, quelque soit la position du curseur.
Ctrl-V
Lors d'une saisie de texte, Ctl-V permet l'insertion de caractères de contrôle. Par exemple, les deux lignes suivantes sont équivalentes :
echo -e '\x0a' echo <Ctl-V><Ctl-J>
Ctrl-V est utile principalement dans un éditeur de texte.
Ctrl-W
Lors de la saisie d'un texte dans une console ou un terminal graphique, Ctrl-W efface les caractères à partir du curseur, à reculons jusqu'au premier blanc. Avec certains paramétrages, Ctrl-W efface à reculons jusqu'au premier caractère non alphanumérique.
Ctrl-X
Dans certains traitements de texte, coupe le texte surligné et le place dans le presse-papier.
Ctrl-Y
Colle le texte à l'endroit où il a été supprimé (avec Ctrl-U ou Ctrl-W).
Ctrl-Z
Met en pause un job en avant-plan.
Opération de substitution dans certains traitements de texte.
Caractère EOF (end-of-file) dans le système de fichiers MSDOS.
Fonctionne comme un séparateur entre des commandes et/ou des variables. Les blancs peuvent être desespaces, des tabulations, des lignes blanches ou d'une combinaison de ceux-ci. [21] Dans certains contextes, tels que les affectations de variable, les espaces blancs ne sont pas permis et sont considérés comme une erreur de syntaxe.
Les lignes blanches n'ont aucun effet sur l'action d'un script et sont donc utiles pour séparer visuellement les différentes parties.
La variable $IFS est une variable spéciale définissant pour certaines commandes le séparateur des champs en entrée. Sa valeur par défaut est l'espace.
Pour conserver les espaces à l'intérieur d'une chaîne de caractères ou d'une variable, utilisez des guillemets("").
Les filtres UNIX peuvent cibler et opérer sur les espaces en utilisant la classe de caractères POSIX [:space:].
[15] Un opérateur est un agent qui exécute une opération. L'exemple habituel est l'opérateur arithmétique, + - * /. Avec Bash, il y a croisement entre les concepts d'opérateur et de mots clés.
[16]
American Standard Code for Information Interchange. This is a system for encoding text characters (alphabetic, numeric, and a limited set of symbols) as 7-bit numbers that can be stored and manipulated by computers. Many of the ASCII characters are represented on a standard keyboard.
[17] Un PID, ou identifiant de processus, est un numéro affecté à un processus en cours d'exécution. Les PID des processus sont visibles avec la commande ps.
Définition : un processus est un programme en cours d'exécution. On dit parfois un job.
[18] Exception : un bloc de code entre accolades dans un tube peut être lancé comme sous-shell.
ls | { read ligne1; read ligne2; } # Erreur. Le bloc de code entre accolades tourne comme un sous-shell, #+ donc la sortie de "ls" ne peut être passée aux variables de ce bloc. echo "La première ligne est $ligne1; la seconde ligne est $ligne2" # Ne fonctionnera pas. # Merci à S.C.
[19] Même si dans les temps anciens, un philtre désignait une potion dotée de pouvoirs de transformation magiques, un filtre UNIX transforme sa cible d'une façon (à peu près) analogue. (Si un programmeur pouvait réaliser un « philtre d'amour » qui fonctionne sur une machine Linux, il aurait toutes les chances de recevoir honneurs et consécration.)
[20] Bash stocke une liste de commandes auparavant lancées à partir de la ligne de commande dans un tampon, ou dans un espace en mémoire, pour retrouver l'historique à partir des commandes internes de l'historique.
[21] Un saut de ligne (newline) est aussi une espace. Ceci explique pourquoi une ligne blanche, consistant seulement d'un saut de ligne, est considérée comme une espace.