-
Notifications
You must be signed in to change notification settings - Fork 16
/
bash.txt
1731 lines (1543 loc) · 96.5 KB
/
bash.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
BASH_SYNTHESE
/=+===============================+=\
/ : : \
)==: GENERALITES :==(
\ :_______________________________: /
\=+===============================+=/
[VAR=VAL[ VAR=VAL]...] #Exécute FILE comme un script, bash s'il y a le shabang
bash FILE #bash au début. Si FILE est dans le répertoire courant,
[VAR=VAL[ VAR=VAL]...] #et que le répertoire courant n'est pas dans $PATH, FILE
FILE #ne peut être invoquée sous la seconde forme que précédé
#de ./
#FILE doit être exécutable sous la seconde forme, et
#lisible sous la première.
#Toute VAR déclarées en préfixant VAR=VAL fait partie de
#de l'environment de FILE.
#Marche aussi sur une commande externe.
bash -c STRING #Exécute STRING.
bash -s #Exécute stdin
BASH UTILISE ==> #Le Bash utilisé par chaque user est défini dans
#/etc/passwd. bash, sh, etc. tapé dans un terminal
#bascule le shell utilisé.
BUILTINS OU COMMANDE #Bash est composé de mots-clef comme { }, etc. et de
EXTERNE ==> #commandes builtins (ou primitives), comme echo ou test.
#Tout est stocké dans /bin/bash.
#Il est cependant possible de faire appel à des
#commandes externes, comme cp ou find, qui seront alors
#stockées n'importe où (exemple : /usr/bin/locale).
#Les builtins, contrairement aux commandes externes, ne
#forkent pas. Elles sont ainsi plus rapides
#L'utilisation de built-ins aux dépens de commandes
#externes, même aux dépens de la longueur ou simplicité
#du code, améliore souvent beaucoup les performances,
#parfois jusqu'à un facteur 100, donc essayer de faire
#du full-bash autant que possible !
#De nombreux builtins sont disponibles néanmoins en
#tant que commandes externes dans /bin
#Ce document ne fait jamais intervenir de commandes
#externes (ou le précise) : il est full-bash
#Voir la doc pour les builtins restants
SHELL INTERACTIF #Un shell est interactif lorsque tout son input
OU NON ==> #provient de l'utilisateur (le cas d'une console)
#!/bin/bash #"Shebang" En debut de script, indique le bash utilise.
#! /bin/bash #Préférer la première version.
# COMMENTS #Commentaires (#doit etre precede d'un whiteline)
: <<STRING
COMMENTS #Commentaires places grace a un here document
STRING #redirigeant vers true. Evite de retaper le #.
; ET NEWLINE ==> #Une ligne de commande se termine par une newline ou un
#point-virgule. Il est donc necessaire quand un script
#tient sur une seule ligne (par exemple dans une
#console ) de separer avec un ; ou d'echapper la
#newline en tapant \ puis entree.
IFS ==> #La variable IFS exécute le "word splitting". Ce dernier
#divise en plusieurs tokens le résultat :
# - d'une parameter expansion (dont $VAR)
# - d'une arithmétique expansion $(( )) et $[ ]
# - d'une commande substitution $( ) et ` `
#et ce en fonction des diviseurs présent, caractère par
#caractère, au sein d'$IFS (par défaut $' \t\n')
#Pour le changer, ne pas oublier de le sauvegarder et
#de le remettre.
\ #echappe le caractère suivant
'' #echappe tout sauf ' (l'échapper avec '\''). Les
#trailing backslashs deviennent des backslashs littéraux
"" #echappe tout, dont :
# - globbing
# - les whitespaces
# - '
# - <(COMMANDES) et >(COMMANDES)
# - ~
# - {0..9} et {1,2}
#sauf :
# - `COMMANDES`
# - toute expansion commençant par $ :
# - $VAR
# - $1
# - ${ARR[@]}
# - ${#VAR}
# - ${VARPATTERN}
# - ${VAR:-STRING}
# - $(( ))
# - $[ ]
# - $(COMMANDES)
# - etc.
# - "
# - ! non suivi d'un whitespace
# - \ suivi de ` $ \ " ou newline (trailing backslash
# supprimé)
#Des doubles guillemets au sein d'un ${ } ou d'un $( )
#ne referment pas les guillemets précédentes (s'il y en
#a), mais en ouvrent d'autres, nested.
$'MESSAGE' #permet d'utiliser toutes les sequences d'echappement
#(voir doc). \c est interprété comme \cCHAR ou, seul,
#comme un backslash n'échappant pas les newlines. Null
#Arrête la string.
#Les guillemets sont simples, non doubles
$"STR" #Equivaut à "$(gettext "STR")" : cf gettext
$RANDOM #renvoie un nombre pseudo-aleatoire (entre 0 et 32767)
command_not_found_ #Fonction exécutée lors de l'invocation d'un programme inconnue. Peut être redéfini.
handle #Par défaut : sleep 2; echo "$1: command not found"
LIMITE DU NOMBRE #Attention, car une ligne de commande ne peut pas
D'ARGUMENTS SUR UNE #excéder un certain nombre d'octets. Celui-ci peut être
LIGNE DE COMMANDE ==> #retrouvé grâce à getconf ARG_MAX. Cette limite est
#propre au noyau, et est de 128 Ko la plupart du temps.
#C'est la seule limite existante.
#Ainsi, un * peut faire référence à une myriade de
#fichiers et faire planter une commande par exemple :
#préférer donc faire une exécution par fichier dans
#une boucle, qu'une exécution pour plusieurs fichiers.
FORMAT DES NOMBRES ==> #Ils sont comme des signed long long int :
# - entiers : les floats sont tronqués
# - avec overflow, deviennent 0
# - peuvent être négatifs
/=+===============================+=\
/ : : \
)=\: DECLARATION ET :/=(
)=/: DEFERENCEMENT DE VARIABLES :\=(
\ :_______________________________: /
\=+===============================+=/
VAR="2" #Declaration de variable. Jamais d'espace autour de =
declare VAR1="VALEUR1" #sauf entre (( )) et avec let. Les variables (a moins
"VAR2=VAL2" "VAR3=VAL3" #d'utiliser declare) sont toutes des strings utilisees
set VAR="VALEUR" #differemment selon le contexte. Par convention mettre
#les variables globales en majuscule, et locales en
#minuscule. Seules les lettres, chiffres (pas en debut
#de nom) et _ sont autorises dans les noms de variables
VAR_PATH="/home/user/" #utile pour ne pas avoir a retaper un chemin partiel
#ou un fichier et son chemin
VAR=VAL[, VAR2=VAL2]... #Il est possible de mettre plusieurs déclarations à la
VAR=VAL[ VAR2=VAL2]... #suite sur la même ligne ainsi.
typeset
set #Affiches toutes les variables declarees (dont
declare #environment variables)
declare -p #Même chose, mais imprime le type avec.
declare -f #Même chose, mais seulement pour les fonctions et leur
#définition.
declare -f #Même chose, mais seulement pour les fonctions, sans
#leur définition.
declare -p VAR #Affiche le type et la valeur de la variable (sauf s'il
#s'agit d'une fonction)
declare -F FONC_VAR #Imprime FONC_VAR si FONC_VAR a été déclaré.
typeset #synonyme de declare, mais déprécié
declare -a VAR #type une variable en tant qu'array non-associative
declare -A VAR #type une variable en tant qu'array associative
declare -f VAR #type une variable en tant que fonction. Si elle existe
#déjà, affiche cette fonction et sa définition.
declare -i VAR #type une variable en tant qu'integer. Les valeurs qui
#lui seront assignées seront toujours évaluées
#arithmétiquement
declare -r VAR
readonly VAR #rend une variable read-only
readonly -a VAR #Type une variable comme array non-associative read-only
readonly -A VAR #Type une variable comme array associative read-only
readonly -f VAR #Type une variable comme fonction read-only
readonly -p #Imprime une liste de toutes les read-only variables
declare -t FUNC #La fonction héritera des traps RETURN et DEBUG du shell
#parent.
declare -l VAR #la variable ne pourra contenir que des caractères
#lowercase (il est possible de lui assigner des
#uppercase mais ils sont automatiquement convertis)
declare -u VAR #Même chose, mais en uppercase
declare -c VAR #le premier caractère de la variable sera toujours
#uppercase et les suivants lowercase (même remarque que
#précédemment pour la conversion et l'assignation)
declare +a VAR #enleve le typage Array. Meme chose pour +f,+i,+p,etc.
declare -a VAR="VALEUR" #il est possible d'assigner une valeur avec declare
#mais reduit la portee d'une variable a l'interieur
#d'une fonction
$VAR #utiliser la valeur d'une variable. ne pas oublier $
${VAR} #meme chose. parfois pour eviter une ambiguite. Ex :
#VAR=${VAR}2 pour ajouter un 2 a la fin de $VAR. $VAR2
#echouerait
"$VAR" #cette version doesn't squeeze multiple whitespaces
#into single ones as $VAR does. De plus, contrairement à
#$VAR, les nulls sont conservés. Ainsi echo -e "\0"
#imprime un null contrairement à echo -e \0 ou à echo -e
#$'\0'
POINTEUR="VALEUR" #reference indirect : fait reference a la valeur de la
VAR="POINTEUR" #valeur d'une VAR. Ici, \$$VAR signifie $POINTEUR soit
eval "VAR=\$$VAR" #VALEUR. $$VAR est une erreur de syntaxe. Sans eval,
(ou eval eval "VR=$VR") #VAR deviendrait "$POINTEUR" et non "VALEUR".
${!VAR} #Est equivalent a \$$VAR mais mieux car il n'a pas
#besoin d'eval pour eviter de renvoyer "$POINTEUR" :
#il renvoie toujours "VALEUR"
POINTEUR2="VALEUR"
POINTEUR1="POINTEUR2"
VAR="POINTEUR1"
eval "VAR=\$$VAR"
eval "VAR=\$$VAR" #On peut multiplier les references indirectes
$_ #dernier argument utilise
NULL ==> #Null et "" sont la meme chose
unset VAR #Remplace la valeur de VAR par une chaine vide.
VAR="" #Most of time, une variable qui n'existe pas, egal a
VAR= #"" ou a null are the same (exception pour les arrays)
#La variable reste declaree
unset -f VAR #Ne marche que sur les fonctions.
unset -v VAR #Ne marche que sur les variables.
/=+===============================+=\
/ : : \
)==: ARRAYS :==(
\ :_______________________________: /
\=+===============================+=/
NULL ET ARRAYS ==> #Un null dans une array est tout de meme un element
ASSOCIATIVE ARRAYS ==> #Il est possible d'utiliser des STRINGS comme index : on
declare -A ARR ==> #parle alors d'associative arrays.
#Il faut auparavant obligatoirement les déclarer avec
#declare -A ARR
#Elles s'utilisent de la même manière, sauf que la forme
#ARR=( ... ) est prohibée. Seul ARR[INDEX]="VALEUR" est
#possible pour modifier ou ajouter des valeurs.
#Le reste est identique
#Il s'agit d'une fonction de Bash 4
ARR=( "VALEUR" ... ) #declaration d'array. Ce qui sépare les différentes
#VALEUR d'une array lors de l'affectation est un espace
#non échappé (guillemets ou backslash)
ARR=( [N1]="VAL1"... ) #permet d'assigner un index customisé a chaque variable
ARR=( $VAR ) #Si $VAR est une chaine de mots separes par des espaces
#(par exemple "$@"), transforme cette chaine en array
#ARR. Attention : pas de guillemets
ARR1=( ${ARR2[@]} ) #Il est possible de copier une array ainsi
ARRAY1=( ${ARRAY2[@]}
${ARRAY3[@]} ) #concatene deux arrays
ARR+=( VAL ) #ajoute une valeur a la fin de l'array. Ne marche pas
#avec les arrays associatives. VAL peut être une suite
#de VAL ou de ${arr[@]}, etc.
ARR[INDEX]="VALEUR" #modification d'une valeur. L'index commence a 0. Il est
#possible de creer une array ainsi quel que soit INDEX
#(comble les valeurs precedentes par des null).
unset ARR[INDEX] #supprime complètement une valeur de l'array
${ARR[INDEX]} #renvoit la valeur de l'array a tel index. $ARR[INDEX]
#ne marche pas.
${${ARR[* ou INDEX]}}
==> ERREUR #mauvaise syntaxe. utiliser ${VAR[* ou INDEX]}
"${ARR[@]}" #renvoit l'ensemble des valeurs de ARR, séparés les
#unes des autres par un espace non échappé (il s'agit
#donc d'une suite de STRINGS et non d'une seule
#STRING). Les valeurs ne sont pas splittées.
#$ARR et ${ARR} équivalent à ${ARR[0]}
#Utile dans les boucles for : for VAR in "${ARR[@]}"
"${ARR[*]}"
${ARR[*]} #Comme ce qui précède, mais avec les mêmes différences
${ARR[@]} #que celles entre "$*", $* et $@ (voir ces derniers)
"${!ARR[@]}"
"${!ARR[*]}"
${!ARR[*]} #même chose mais renvoie l'ensemble des indexs, et non
${!ARR[@]} #des valeurs
${#ARR[*]}
${#ARR[@]} #renvoie le nombre de valeurs de l'array
VARIABLES UTILISEES #Si une variable est utilisee dans une operation prevue
COMME ARRAYS ==> #pour les arrays, elle ne renvoie pas d'erreur et est
#consideree comme une array a un seul element. Ex :
#"${#VAR[@]}" renvoie "1".
ARR[INDX]="VAL" || echo #certains shells bashs ne supportent pas les arrays.
"Array non supporte" #ceci est un test de validation.
MULTIDIMENSIONNAL ARRAYS#Pas supportées, mais on peut utiliser des arrays associatives pour simuler :
==> # - declare -A Matrice
# Matrice[3;5]=VAL
# echo ${Matrice[$a;$b]}
/=+===============================+=\
/ : : \
)==: ARGUMENTS POSITIONNELS :==(
\ :_______________________________: /
\=+===============================+=/
ARGUMENTS NULL ==> #Il est possible de passer des arguments null
$0 #nom/chemin du script lui-meme (ex: "./scrip.sh") tel
#qu'il a été invoqué. Renvoie "bash" dans un login
#ou interactive shell. Plus user-friendly :
# - $(basename $0) ou $(basename $0 .sh)
$1, $2, etc. #arguments utilisés.
${10},${11},etc. #correcte notation apres $9 mais fonctionne aussi avant
$#
${#*}
${#@} #nombre d'arguments (sauf $0)
${!#} #dernier argument positionnel
"$*" #renvoie l'ensemble des arguments en échappant tous les
#les IFS, l'ensemble étant alors considéré comme une
#seule STRING
$* #Renvoie l'ensemble des arguments en n'échappant aucun
$@ #IFS, que ce soit entre les arguments ou en leur sein.
#Les arguments sont ainsi considérés comme des STRINGS
#séparés, mais les arguments contenant en leur sein un
#IFS seront splittés.
"$@" #Renvoie l'ensemble des arguments en échappant les IFS
#au sein des arguments, mais pas entre eux. Ainsi, ils
#ne sont pas splittés, mais sont considérés comme des
#STRINGS séparés
#Préférer cette syntaxe
${$* etc.
${$@ etc. #Cette structure est erronee, il faut utiliser ${*, ${@
${$1, ${$2 etc. ==> ERR #et ${index etc. a la place
shift N #shift la liste d'arguments de N vers la gauche. Utile
#par exemple dans une boucle while (( $# )) qui est
#Renvoie true si $# != 0
set -- [STRING...] #Les arguments sont remplacés par STRING...
#Penser a les sauvegarder donc si l'on veut les
#reutiliser.
#Si STRING est absent, supprime donc les arguments.
COMMANDE -- ... #End of options flag : tout ce qui suit -- est un
#argument et non une option, même s'il commence par un
#tiret. Ne marche pas avec toutes les commandes (par
#exemple echo)
while getopts ... #Utiliser getopts pour procéder les options (voir doc)
/=+===============================+=\
/ : : \
)==: FONCTIONS :==(
\ :_______________________________: /
\=+===============================+=/
NOM () { #declare une fonction. $1 $2 etc. sont updates en
COMMANDES #fonction des parametres passes en appelant la
} #$0 reste inchange cependant. ${FUNCNAME[0]} (ou
function NOM { #$FUNCNAME) enregistre le nom de la fonction courante,
COMMANDES #${FUNCNAME[1]} celui de la fonction ayant appelé cette
} #fonction, etc. Il est possible de passer des arguments
function NOM () { #null.
COMMANDES #Preferer la première syntaxe. Il peut etre interessant
} #de redefinir une fonction ou de la definir
#differemment en fonction d'une condition. Une fonction
#peut etre récursive. Les arguments positionnels restent
#locaux, mais pas les variables, auquel il faut donc
#penser à apposer le keyword "local"
#Une fonction peut aussi être une collapsing function,
#c'est-à-dire qu'elle refait une définition
#(déclaration) d'elle-même, au sein d'elle-même. La
#nouvelle définition de la fonction ne sera lue qu'à
#la prochaîne exécution de la fonction
#Les noms de fonctions ne sont pas techniquement des
#variables : il est possible d'assigner une variable et
#une fonction avec le même nom.
#{ COMMANDES } peut aussi être non un bloc { } mais
#une structure ou boucle (mais pas une commande simple)
function NOM () { #Mettre un ; avant et après le second crochet si le tout
COMMANDES ; } ; #tient sur une seule ligne
return [NOMBRE] #return est l'"exit" des fonctions et des fichiers
#sources. NOMBRE est 0 par défaut. Une fonction fait un
#return 0 à la fin de son exécution.
local VAR #rend locale la portee d'une VAR. Utilisee dans les
local VAR=VALEUR #fonctions uniquement, notamment les recursions, pour
typeset VAR #que chaque boucle recursive n'ecrase pas la VAR de la
typeset VAR=VALEUR #boucle precedente (principalement si des COMMANDES
declare VAR #sont effectues apres la fin de chaque boucle recursive
declare VAR=VALEUR #a l'aide de la VAR conservee et propre a cette boucle
caller [NOMBRE] #A l'intérieur d'une fonction ou d'un fichier sourcé,
#affiche :
# - le numéro de ligne
# - le nom de la fonction (ou "main" s'il ne s'agit
# pas d'une fonction)
# - le nom du fichier
#depuis laquelle a été lancée cette fonction, ou sourcé
#ce fichier, en remontant dans l'arborescence NOMBRE
#fois (par défaut 0)
#Si NOMBRE n'est pas précisé, n'affiche pas le nom de
#la fonction (ou "main")
{ #"fonction" anonyme. Permet les redirections du bloc
COMMANDES #entier et son utilisation comme une seule COMMANDES
} #(pipeline).
#Les COMMANDES sont exécutées immédiatement. On ne peut
#pas rendre la portée des variables locale, ni utiliser
#return ou caller.
#Un whitespace doit séparer { de COMMANDES
/=+===============================+=\
/ : : \
)==: SUBSTITUTION DE COMMANDES :==(
\ :_______________________________: /
\=+===============================+=/
`COMMANDES` #Renvoie le resultat d'une commande. Si des $IFS sont
#presents, ils coupent le resultat en plusieurs chaines
#COMMANDES peut meme etre un loop, etc.
#Remplace les newlines par des espaces.
#Attention : lance un sub-shell
#Il est possible de lancer un autre langage ainsi et
#d'en avoir le resultat. Ex : `python script.py`
$( COMMANDES ) #meme chose, mais meilleure syntaxe. Permet :
# - des nested structures (peut être fait avec ` `,
# mais ils doivent être échappés
# - de mieux prendre en charge les séquences
# d'échappement backslash lorsqu'entouré de double
# guillemets. Ex: "`echo -e 1\\\\n2`" peut être écrit
# "$(echo -e 1\\n2)"
eval "COMMANDES" #Execute "COMMANDES" (qui peut donc venir de
#l'expansion d'une $VAR), sans rien renvoyer.
#En général obsolète, sauf quelques cas, par exemple
#forcer l'expansion de la valeur contenue dans les
#variables contenues dans COMMANDES. Exemple :
# - var="'un deux'" ; echo "$var" --> 'un deux'
# - var="'un deux'" ; eval 'echo "$var"' --> un deux
/=+===============================+=\
/ : : \
)==: TESTS :==(
\ :_______________________________: /
\=+===============================+=/
TEST ==> #Voici les valeurs possibles de TEST :
[ OPERATION LOG. ]
test OPERATION LOG.
[[ OPERATION LOG. ]] #Voir plus bas
let 'OPERATIONS
ARITHMETIQUES'
(( OPERATIONS
ARITHMETIQUES )) #voir plus bas
COMMANDES #le test execute Then si la commande reussit (exit code
#de 0)
FONCTION #vrai si la fonction retourne un exit code de 0
true #Renvoie toujours 0. exemple : while true etc.
: #Ne marche qu'en dehors d'une structure de test ( [ ]
#[[ ]] (( )) ou autres)
#A noter que : > "FILE" vide un fichier a 0 bits sans
#pour autant le supprimer ou en changer les permissions
false #renvoit toujours faux
#Ne marche qu'en dehors d'une structure de test ( [ ]
#[[ ]] (( )) ou autres)
: COMMANDES #Renvoient toujours vrai (ou faux) même si COMMANDES
true COMMANDES #contient des erreurs (et n'affiche pas ces erreurs)
false COMMANDES #Ainsi :
# - : $(( OPER. ARI )) exécute OPER. ARI, mais n'envoie
# pas de message d'erreur (car il n'y a pas de
# commande à proprement parler)
OPERATIONS BOOL. ==> #Un TEST peut aussi être la combinaison de deux TEST :
TEST && TEST #Et logique entre deux tests
TEST || TEST #Ou logique entre deux tests
! TEST #Non logique sur un test
( TEST... ) #La valeur logique des TEST... liés entre eux par des
#&&, || et ! est calculée prioritairement
CALCUL DE LA VALEUR #La valeur logique se calcule de gauche à droite, en
LOGIQUE ==> #commençant par calculer les parenthèses. Exemple :
# - true && false || ! ( true && true )
# --> true && false || ! ( true )
# --> true && false || false
# --> false || false
# --> false
! && et || à l'intérieur#! && et || peuvent être placés à l'intérieur même d'un
même d'un TEST ==> #(( )), d'un [[ ]] ou d'un [ ] sous la forme par
#exemple :
# - (( OPERATION ARI. || OPERATION ARI. && ... ))
# - [[ ! OPERATION LOG. || OPERATION LOG. ]]
# - etc.
#Cependant, [ ] n'accepte que !, car && et || sont
#nommés -a et -o :
# - [ OPERATION LOG. -a OPERATION LOG. -o ... ]
#De plus, (( )) accepte & et | comme équivalent de && et
#de ||, mais ceux-ci sont dépréciés
(( OPER1 , OPER2 )) #A l'intérieur de ces structures pour opérations
$(( OPER1 , OPER2 )) #arithmétiques, OPER2 sera exécutée quelle que soit la
$[ OPER1 , OPER2 ] #valeur logique de OPER1, et seul la valeur logique
let'OPER1 , OPER2' #d'OPER2 sera renvoyée
ET-CHAINES ET #Les syntaxes suivantes permettent de se passer de
OU-CHAINES ==> #structures et de boucles pour utiliser un TEST.
TEST... && COMMANDES #execute COMMANDES entre parentheses si la valeur des
#TEST... précédents est vraie
TEST... || COMMANDES #execute COMMANDES entre parentheses si la valeurs des
#TEST... précédents est fausse
CMAND && CMAND && CMAND #execute chaque COMMANDE a condition que la precedente
&& etc. #reussisse (quel que soit l'état de toutes celles
#précédant la précédente)
CMAND || CMAND || CMAND #execute chaque COMMANDE a condition que la precedente
|| etc. #echoue (même chose)
CMAND1 && CMAND2 ||
CMAND3 && TEST || CMND4 #Exemple de structure complexe
/=+===============================+=\
/ : : \
)==: OPERATIONS ARITHMETIQUES :==(
\ :_______________________________: /
\=+===============================+=/
$VAR DANS LES OPERATIONS#Il n'est pas necessaire d'ajouter un $ devant VAR pour
ARITHMETIQUES ==> #la substituer, c'est même non recommandé
STRING DANS LES
OPERATIONS ARI. ==> #Les STRINGS ont une valeur de 0
CHIFFRES DECIMAUX == > #Bash ne comprend pas . ou , et tout nombre est
#directement tronqué
`expr OPERATION ARI.` #Renvoie le resultat d'une operation arithmetique (dont
$( expr OPERATION ARI. )#comparaisons et operations booleennes). 0 = faux, 1 =
#vrai. Les declarations ne sont pas effectuees.
#Preferer (( )) et let.
#expr est une commande externe
$[ OPERATION ARI. ] #Effectue et renvoie le resultat d'une operation
#arithmetique (ce qui inclue les comparaisons et
#operations booleennes). 0 = faux et 1 = vrai
#(ne pas confondre avec les exit codes)
#Les declarations de variables telles $[VAR = VAR+1] ou
#$[VAR++] sont opérées. Elles ne sont qu'arithmetiques,
#il n'est par exemple pas possible d'assigner une
#"STRING" à une VAR. Elles viennent en dernier dans
#l'ordre d'enchainement des opérations arithmétiques
#Respecter les espaces autour de [ ]
let 'OPERATION ARI.' #Comme $[ ] mais a une valeur de TEST egalement.
(( OPERATION ARI.)) #Prefere a $[ ]. Exemple : if (( VAR < 5 )). Autre
#Même chose pour les déclarations.
#Respecter les espaces autour de (( ))
$(( OPERATION ARI. )) #Seul moyen (avec let 'VAR = (( OPERATION ARI. ))') de
#renvoyer le resultat de (( OPERATION ARI. )). Ce
#résultat est celui de l'operation, de la variable
#déclarée ou bien 1(vrai) ou 0(faux) s'il s'agit d'une
#comparaison ou d'une operation booleenne)
#Effectue l'opération arithmétique, de même que (( ))
: $(( OPERATION ARI. )) #Equivalent de (( )) pour toutes les situations, mais
#plus portable
OPERATION ARI. ==> #Voici la liste de ce que peut contenir une OPERATION
#ARI. :
+ - * / #arithmetique de base. VAR=VAR+1 concatene seulement
#"+1" a la fin de VAR. pour declarer une variable en
#utilisant des operations arithmetiques, il faut
#utiliser les formes : VAR=$[VAR+1], (( VAR = VAR+1 ))
#ou let 'VAR = VAR+1'
% #modulo
** #puissance
VAR++ VAR-- #post-incrementation. Utiliser $[ ] let ou (( ))
++VAR --VAR #pre-incrementation.
+= -= *= /= %= #declaration arithmetique. meme remarque.
< <= > >= == #comparaisons
== != #egal et inegal
<< #bitwise left shift
<<= #bitwise left-shift-equal
>> #bitwise right shift
>>= #bitwise right-shift-equal
& #bitwise AND
&= #bitwise AND-equal
| #bitwise OR
|= #bitwise OR-equal
~ #bitwise NOT
^ #bitwise XOR
^= #bitwise XOR-equal
0NOMBRE #nombre octal (considere comme une operation
#arithmetique : utiliser donc les bonnes structures)
#Sera toujours imprimé et lu en octal
0xNOMBRE #nombre hexadecimal. Sera toujours imprimé et lu en
#hexadécimal
2#NOMBRE #nombre lu comme binaire (le $ est obligatoire même
2#$VAR #entre (( )) ) (mais ne pourra être affiché qu'en
#décimal)
N#NOMBRE #nombre lu comme étant de base N (mais ne pourra être
N#$VAR #affiché qu'en décimal)
$(( N#NOMBRE )) #renvoie NOMBRE, base N, converti en décimal
OPER1 ARI. ? OPER2 ARI. #Renvoie OPER2. ARI si OPER1 ARI. est vraie, sinon
: OPER3 ARI. #renvoie OPER3. ARI. C'est une construction trinaire
#C-style
/=+===============================+=\
/ : : \
)==: OPERATION LOGIQUE :==(
\ :_______________________________: /
\=+===============================+=/
[ OPERATION LOG. ] #Effectue un TEST en fonction de l'OPERATION LOG.
test OPERATION LOG. #la commande test et [ ] sont equivalentes.
[[ OPERATION LOG. ]] #La deuxième structure est à préférer. Voici ses ajouts
#par rapport à la structure [ ] :
# - [[ ]] est plus rapide que (( )), qui est plus
# rapide que [ ]
# - Ne provoque pas d'erreur si une $VAR non échappée
# contient une whitespace ou un control character.
# $VAR n'a jamais donc besoin d'être échappé,
# contrairement à [ ]
# N'échapper donc que les wildcards si elles doivent
# être prises dans leur sens littéral : échapper donc
# les variables d'un test [[ == ]] ou !=, car elles
# sont susceptibles de contenir des crochets, qui
# font échouer les tests.
# - Avec les OPERATION LOG. -eq, -ne, -lt, -le, -gt et
# -ge, possibilité d'utiliser :
# - les opérateurs arithmétiques + - * / %
# et ** (à condition qu'ils soient
# immédiatement suivis et précédés d'un nombre
# ou de $VAR, et non d'un espace)
# - les formes 0NOMBRE, 0xNOMBRE et 2#NOMBRE
# - > et < ne doivent pas être échappés
# - -a et -o sont remplacés par && et || (voir plus
# haut)
# - [[ ]] est insensible à la casse après un "shopt -s
# nocasematch"
# - moins portable cependant
# - le globbing sur les tests de FILE est impossible,
# contrairement à [ ]. Le globbing sur les tests ==
# = et != est quant à lui possible
# - l'opérateur =~ est disponible
OPERATION LOG. ==> #Voici une liste des OPERATION LOG. possibles :
[[ -z $VAR ]] #$VAR doesn't exist ou est null.
[[ $VAR ]]
[[ -n $VAR ]] #$VAR exists et est non null
STRING DANS LES #Les STRINGS ont une valeur de 0 dans les tests -eq, -ne
OPERATIONS ARI. ==> #-lt, -le, -gt et -ge
[[ NOMBR1 -eq NOMBR2 ]] #NOMBR1 est arithmetiquement egal a NOMBR2. Il peut
#s'agir de $VAR ou de VALEUR
[[ NOMBR1 -ne NOMBR2 ]] #NOMBR1 est arithmetiquement inegal a NOMBR2.
[[ NOMBR1 -lt NOMBR2 ]] #NOMBR1 est arithmetiquement inferieur a NOMBR2.
[[ NOMBR1 -le NOMBR2 ]] #NOMBR1 est arithmetiquement inferieur ou egal a NOMBR2
[[ NOMBR1 -gt NOMBR2 ]] #NOMBR1 est arithmetiquement superieur a NOMBR2.
[[ NOMBR1 -ge NOMBR2 ]] #NOMBR1 est arithmetiquement superieur ou egal a NOMBR2
[[ STRING1 == STRING2 ]]#Strings are alphabétiquement equal. Il peut s'agir de
[[ STRING1 = STRING2 ]] #STRING ou "STRING". La seconde syntaxe est à déprécier
[[ STRING1 != STRING2 ]]#Strings are not equal alphabetiquement
[[ STRING1 < STRING2 ]] #STRING1 est alphabetiquement avant STRING2. L'ordre
[ STRING1 \< STRING2 ] #dépend peut-être de la locale, mais pour moi, cela
#donne, du plus petit au plus grand :
#
# ` ^ ~ < = > | space _ - , ; : ! ? / . ' " ( ) [ ] {
# } @ $ * \ & # % +
# NUL->\x1f, DEL
# 0123456789
# aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ
[[ STRING1 > STRING2 ]]
[ STRING1 \> STRING2 ] #STRING1 est alphabetiquement apres STRING2.
[[ -a FILE ]]
[[ -e FILE ]] #FILE exists. -a is deprecated
[[ -s FILE ]] #FILE has a size greater than zero.
[[ -f FILE ]] #FILE is a regular file (and exists).
[[ -d FILE ]] #FILE is a directory (and exists).
[[ -h FILE ]]
[[ -L FILE ]] #FILE is a symbolic link (and, etc. for all the list)
[[ -b FILE ]] #FILE is a block-special file.
[[ -S FILE ]] #FILE is a socket.
[[ -c FILE ]] #FILE is a character-special file.
[[ -p FILE ]] #FILE is a named pipe (FIFO).
[[ -r FILE ]] #FILE is readable.
[[ -w FILE ]] #FILE is writable.
[[ -x FILE ]] #FILE is executable.
[[ -u FILE ]] #SUID (set user ID) bit is set.
[[ -g FILE ]] #SGID bit is set.
[[ -k FILE ]] #Sticky bit is set.
[[ -O FILE ]] #FILE is owned by the effective user ID.
[[ -G FILE ]] #FILE is owned by the effective group ID.
[[ -N FILE ]] #FILE has been modified since it was last read.
[[ FILE1 -nt FILE2 ]] #FILE1 older than FILE2, or FILE1 exists and
#FILE2 does not
[[ FILE1 -ot FILE2 ]] #FILE1 newer than FILE2, or FILE2 exists and
#FILE1 does not
[[ FILE1 -ef FIL2 ]] #FILE1 and FILE2 are the same device and inode
[[ -o OPTION ]] #Shell OPTION is enabled (long name d'option simple)
[[ -t NOMBRE ]] #Filedescriptor NOMBRE existe dans le shell courant
[[ STRING =~ PATTERN ]] #Test si la premiere chaine contient PATTERN.
#Regexps étendues (sauf \b, \B, \<, \>, \1...), et rien
#dans le PATTERN ne doit être échappé (ni guillemets,
#ni backslash (sauf littéral))
#Préférer [[ STRING == *PATTERN* ]], 2 fois plus rapide,
#si PATTERN peut être fait en globbing sans regexps.
/=+===============================+=\
/ : : \
)==: BOUCLES ET STRUCTURES :==(
\ :_______________________________: /
\=+===============================+=/
if TEST ; then
COMMANDES
elif TEST ; then
COMMANDES #il est plus propre de mettre then sur la meme
else #ligne que if ou elif, separe par un ; et else et fi
COMMANDES #sur des lignes isolees
fi #elif ... et else ... sont falcultatifs
for VAR in LIST ; do #execute COMMANDES pour chaque element de LIST, chaque
COMMANDES #élément devenant a tour de rôle VAR
done #Si la liste est absente, il s'agit de "#@"
#Une LIST est une suite d'éléments séparés par un IFS
#non échappé (guillemets ou backslash) : généralement,
#un espace séparant deux STRINGS ou une newline
#La suite d'éléments peut être obtenue par une
#sustitution de variable, de commandes, etc.
#Exemple de LIST :
# - {1..100}
# - "$@"
# - "${ARR[@]}"
# - ./*.txt
# - "VAL1" "VAL2"...
# - "$VAR1" "$VAR2"...
# - VAR... contenant chacune une suite de "VAL"... (et
# non "VAR" qui échapperait les espaces entre ces
# "VAL")
#Jamais de guillemets autour de VAR
for (( OPER1 ; OPER2 ; # 1) OPER1 s'exécute initialement
OPER3 )) ; do # 2) Ensuite, si OPER2 renvoie vrai, COMMANDES
COMMANDES # puis OPER3 s'exécute. Itération de l'étape 2
done # 3) Si OPER2 renvoie faux, la boucle s'arrête
#OPER sont des opérations arithmetiques.
#Attention, 2 fois moins rapide que la syntaxe
#précédente : utiliser de préférence for VAR in {1..8}
for (( OPER1
[ , OPER1]... ; OPER2
[ , OPER2]... ; OPER3 #Il est impossible d'avoir plusieurs OPER1, OPER2 ou
[ , OPER3]... )) ; do #OPER3 en les séparant par des virgules.
break #Dans une boucle for, while ou until, clot la boucle.
break CHIFFRE #Même chose, mais clot N-1 boucles superieures
#egalement (if loops are nested)
continue #Dans une boucle for, while ou until, effectue une
#nouvelle iteration sans aller jusqu'au bout de celle
#en cours
continue CHIFFRE #Effectue un continue au niveau N-1 superieur, fermant
#les boucles inferieures demarrees
while TEST ; do #Execute tant que le test est vrai ou break ou
COMMANDES #continue (optionnels) Ex : while [ "$a" -lt 3 ].
done #Autre ex : ou while (( a < 3 ))
while true ; do ... #dure toujours jusqu'a interruption ou break
while read VAR ; do ... #Avec une redirection de l'input de read, dure jusqu'a
#la fin de l'input. Ex : while read VAR... < FILE
#lira une ligne de FILE a chaque iteration de la boucle
#Voir plus loin sur les risques de piper l'input d'un
#while read
#De plus, un read embedded dans une telle structure ne
#lira plus l'entrée standard mais FILE. Il faut alors
#inclure un read -u N (qui lira le fdN et non fd0) et
#faire en sorte que fdN pointe vers le terminal et soit
#un input fd : while read VAR... N<&0 < FILE
until TEST; do
COMMANDES
break
continue #execute tant que le test est faux ou break (optionnel)
done #il s'agit d'un while inverse
case "$VAR" in #Exécute les COMMANDES associées au premier PATTERN
PATTERN) #matchant $VAR, puis exécute TERM.
COMMANDES TERM #TERM peut être :
... # - ;; interrompt la structure case
*) # - ;;& continue de rechercher le prochain PATTERN
COMMANDES ;; # parmi tous les PATTERN restants
esac # - ;& exécute les COMMANDES et le TERM du PATTERN qui
# suit immédiatement le PATTERN courant
#;;& et ;& sont des ajouts de Bash 4
#PATTERN utilise le globbing, ainsi que
#PATTERN1|PATTERN2
#PATTERN) peut être sous la forme (PATTERN) : les ( et )
#doivent donc être échappées
#Pour le globbing, pas de guillemets bien sûr
#PATTERN est insensible à la casse après un "shopt -s
#nocasematch"
#Ne pas oublier d'inclure le PATTERN * à la fin, pour
#donner une réponse par défaut.
#Utile pour traiter les options passees par
#l'utilisateur.
select VAR in LIST ; do #Imprime une LIST (même sens que pour for), avec un
COMMANDES #nombre s'incrémentant en face de chaque element, sur
break #stderr.
done #La valeur choisie par l'utilisateur remplace VAR, et
#les commandes sont exécutées.
#La variable REPLY enregistre le nombre tape.
#Si la liste est absente, il s'agit de #@. Si autre
#chose est tape, null remplace VAR.
#PS3 est une variable que l'on peut modifier pour
#changer le texte du prompt.
#Si aucun break n'est rencontre, la boucle se repete.
/=+===============================+=\
/ : : \
)==: REDIRECTIONS :==(
\ :_______________________________: /
\=+===============================+=/
FILE DESCRIPTORS ==> #Un file descriptor (fd) est un lien symbolique vers un
#fichier. Tout fichier ouvert a un file descriptor lié
#à lui.
#Les file descriptors sont listés dans /proc/PROC_NUM/fd
#(PROC_NUM pouvant être "self"). Un nombre leur est
#attribué.
#Un fd peut être :
# - un input fd (recevoir son input du file)
# - un output fd (envoyer son output vers file)
# - un input/output fd (recevoir son input du file, et
# recevoir son output de file)
#D'un point de vue strictement technique, les choses
#sont en fait que tout fd pointe vers un fichier dans le
#même sens : FD --> FICHIER. Seulement la différence est
#au niveau des droits d'accès pour l'user courant :
# - un input fd peut être lu (et donc lire le fichier
# qu'il pointe)
# - un output fd peut être écrit (et donc écrire le
# fichier qu'il pointe)
# - un input/output fd peut être lu et écrit.
#Dans tous les cas, tout fd peut être exécuté
#
LES FD STANDARD ==> #Tout subshell initialise au moins trois fd :
# - /dev/stdin, l'entrée standard, fd 0, input/output
# fd vers le terminal courant (/dev/pts/TERM_NUM),
# mais utilisé par les processus comme un input fd
# - /dev/stdout, la sortie standard, fd 1, input/output
# fd vers le terminal courant (/dev/pts/TERM_NUM),
# mais utilisé par les processus comme un output fd
# - /dev/stderr, l'erreur standard, fd 2, input/output
# fd vers le terminal courant (/dev/pts/TERM_NUM),
# mais utilisé par les processus comme un output fd
#Ainsi, ces trois référence font référence au même
#fichier, en lecture et en écriture. Ce sont les seuls
#fd utilisés par les commandes builtins et externes.
#Pour faire utiliser un fdN à un des fd standards, il
#faut donc le faire indirectement en réassignant leur
#valeurs :
# - N< FICHIER, puis <&N pour fd0 (et non N< FILE, qui
# va modifier le fichier pointé par fdN, mais pas
# celui utilisé par fd0, qui est le fd utilisé par
# les commandes.
# - N> FICHIER, puis >&N pour fd1
# - N> FICHIER, puis 2>&N pour fd2
#Sans les fd standards, elles n'ont pas d'input ou ne
#produisent pas d'output (normal ou flux d'erreurs).
#Supprimer l'un d'eux, ou le modifier d'une mauvaise
#manière peut donc produire une erreur (par exemple,
#si fd0 devient un output fd, il ne pourra plus être lu,
#et si fd1 ou fd2 devient un input fd, il ne pourra
#plus écrire)
#
HERITAGE ==> #Chaque subshell a ses propres fd, qu'il hérite de ses
#parents. Ainsi :
# - ( COMMANDES ) 2>&1 : COMMANDES hérite de 2>&1, mais
# ses fd restent distincts de ceux de son parent
# - ( COMMANDES1 ) 2>&1 | COMMANDES2 : COMMANDES1
# hérite seulement de 2>&1, car pipe et COMANDES2
# est un autre subshell, qui ne lui est pas parent
# (il est en fait enfant du même parent)
#
PORTEE DES #Ainsi une redirection est propre au seul subshell.
REDIRECTIONS ==> #Tout N>, N<, N>&M, |... affectera seulement le subshell
#c'est-à-dire COMMANDES en général.
#En effet, COMMANDES N> FILE ne redirige l'output que du
#subshell créé par COMMANDES
#Pour faire des redirections sur le subshell courant,
#remplacer COMMANDES par exec
#Ainsi, après :
# - exec N>&M ; COMMANDES...
#COMMANDES... est encore affecté par N>&M car c'est le
#subshell qui lance COMMANDES qui a N>&M, dont le
#subshell lancé par COMMANDES hérite donc
#
ORDRE D'EXECUTION ==> #L'ordre d'exécution des redirections est celui-ci :
# - Les fd hérités, du plus haut au plus bas parent
# - Puis la pipe si le subshell est pipé (qu'il
# s'agisse d'une pipe redirigeant son entrée ou sa
# sortie)
# - Enfin les redirections de gauche à droite
#Exemple (redirige stdout et stderr de COMMANDES1 vers
#COMMANDES2 et COMMANDES3 séparément) :
# {
# {
# COMMANDES1 | COMMANDES2
# } 2>&1 1>&4 | COMMANDES3
# } 4>&1
#Ordre d'exécution de :
# - COMMANDES1 : 4>&1 2>&1 1>&4 Pipe_intérieur_ouput
# - COMMANDES2 : 4>&1 2>&1 1<&4 Pipe_intérieur_input
# - COMMANDES3 : 4>&1 Pipe_extérieur_ouput 2>&1 1>&4
# Pipe_extérieur_input (à partir de ce
# point, fd 1 et 2 ne sont plus hérités,
# mais fd 0 et 4 le sont)
#Seul l'ordre de succession des redirections entre elles
#importent, mais leur place dans le subshell est libre,
#sauf :
# - |, |& et <<HEREDOC qui doivent être à la fin du
# subshell
# - les structures, fonctions et blocs (voir ci-
# dessous) doivent précéder les redirections (sauf
# pour un pipe redirigeant leur input)
#Ainsi < FILE COMMANDES équivaut à COMMANDES < FILE
#
OFFSET DES INPUT FD ==> #Un fd a un offset (0 au début). Lorsque des octets sont
#lus ou écrit, ils sont lus à partir de cet offset et
#font avancer cet offset d'autant d'octets.
#Par exemple un read normal fera avancer l'offset du
#nombre d'octets de la ligne lue ou de NOMBRE
#caractères si read a été invoqué avec l'option -n
#NOMBRE
if ... fi > ... #Il est possible de rediriger les fd de tout subshell.
for ... done > ... #Cependant, ces structures :
while ... done | ... # - bloc conditionnel if, case ou select
... | until ... done # - fonction (anonyme ou non)
select ... done 2>&1 # - bloc de commandes
case ... esac > ... # - boucle for, while ou until
[FNCTON] { .. } > ... #Agissent comme si elles étaient des subshells (bien que
( COMMANDES ) > ... #ce soit faux) pour les redirections. Il est donc
#possible de rediriger leurs fd.
#Voir ci-dessous pour les risques de piper leur input
COMMANDES DONT L'INPUT #Il est possible de rediriger l'input de certaines
PEUT ETRE REDIRIGE #commandes, et non d'autres. Celles le pouvant sont
==> #celles :
# - n'acceptant pas d'argument et utilisant par défaut
# stdin (par exemple tr)
# - acceptant stdin par défaut si aucun argument n'est
# attribué
#Dans les deux cas, stdin est lue comme une string, en
#aucun cas comme un nom de fichier. Ainsi :
# - cat FILE | head
#et non :
# - echo FILE | head
#est l'équivalent de :
# - head FILE
#stdin ne sera pas toujours traité exactement de la même
#manière qu'un argument spécifié normalement. Par
#exemple wc FILE affiche le nom de fichier,
#contrairement à wc < FILE