Commande
Les commandes sont les instructions que l'on exécute dans un shell. Elles sont faites pour être :
- spécialisées : elles ne font qu'un seule chose
- paramétrables : des options permettent de changer son comportement par défaut
- automatisables : elles ne demandent (presque) jamais de confirmation de la part de l'utilisateur
Elles sont exécutées :
- dans le dossier courant du shell
- avec un process enfant du shell
Une commande unix peut être utilisée de multiple manière. Le format d'utilisation standard est son nom suivi par des arguments séparées par des espaces. Par exemple :
Les arguments d'une commande peuvent être :
- des options : commence par un
-
- des paramètres : ne commencent pas par un
-
L'exécution d'une commande par le shell se fait plaçant la commande, ses paramètres et ses options dans une liste où le 1er élément est la commande, suivie de ses arguments dans l'ordre d'entrée. Le premier élément de cette liste est exécuté et la liste est passée en paramètre de celle-ci.
La commande echo affiche ses paramètres séparés par un espace puis va à la ligne.
Quel est le résultat de la commande echo coucou !
?
solution
solution
La commande a deux paramètres :
coucou
!
Elle va donc afficher coucou !
puis aller à la ligne.
Pour distinguer les paramètres des options on fait précéder :
- une option courte, c'est à dire composé d'un caractère, par
-
:ls -l
- une option longue, c'est à dire composé d'un mot, par
--
:ls --all
L'intérêt des options courtes est qu'on peut les combiner en ne les faisant précéder que d'un -
. Par exemple ls -lh
est équivalent à ls -l -h
. La plupart des options longues ont leur pendant court, mais ce n'est pas toujours le cas.
Enfin, certaines options nécessitent un paramètre qui doit être donné juste après celle ci. Exemple : ls -hI "I*" ~
va fonctionner (on peut également les "coller" à l'option, comme ça : ls -hI"I*" ~
) alors que ls -Ih "I*" ~
non. Lorsque le paramètre Le paramètre des options longues peut être donné avec un =
, par exemple : ls ~ -h --ignore="I*"
La plupart des commandes fonctionnent sous différents systèmes unix (Linux, Macos, Bsd, ...). Le fonctionnement général de chaque commande est dicté par la norme POSIX mais des variations existent (en particulier les extensions à POSIX dépendent de l'implémentation de la commande et donc du système unix utilisé) il est crucial de se référer à l'aide de son système.
La commande man paramètre
permet d’accéder au manuel du nom de la commande passée en paramètre.
Par exemple man ls
, ou encore man man
pour accéder au manuel de man
.
Le synopsis de la commande permet de donner toutes ses utilisation possible. Son format est déterminée par une norme POSIX :
- en gras : doit être tapé exactement de la même manière
- en italique : à remplacer par les bon arguments
[-abc]
: toutes les options sont optionnelles-a|-b
: les options -a et -b ne peuvent être utilisées en même temps- souligné : l'argument est répétable
Ceci se combine :
- [souligné] : répétable et optionnel
- [expression [argument]] : l'expression est optionnelle et peut être utilisée avec ou sans argument
La plupart des commandes donnent une aide succincte avec l'option -h
ou --help
. Par exemple ls --help
.
Comment faire pour que la commande echo n'aille pas à la ligne à la fin de son exécution ?
solution
solution
C'est l'option -n
.
Attention il faut la mettre en 1er argument, sinon cela ne fonctionne pas.
On peut chaîner les commandes avec ;
. Par exemple : ls ~; echo Fichiers de home
Stopper une commande avec ctrl+C qui envoie le signal SIGINT
Commandes classiques
Linux/Ubuntu possède une grande variété de commandes par défaut (tous les fichiers du dossier /usr/bin
). Certaines demandent des droit d'administrations mais la plupart sont utilisables par tous les utilisateurs.
Indispensables
Un certains nombre de commandes sont indispensable à connaître (pas à maîtriser).
man
cd
ls
cat
,less
(oumore
)touch
echo
rm
etrmdir
mv
grep
sed
,awk
(au moins à quoi ils peuvent servir)find
(au moins à quoi ça peut servir)
Utilisez grep pour connaître le shell de l'utilisateur root
. Il se trouve dans le fichier /etc/passwd
solution
solution
grep root /etc/passwd
Une des commandes ci-dessus n'est pas dans /usr/bin
. Laquelle ?
solution
solution
ls /usr/bin/cd
ls: impossible d'accéder à '/usr/bin/cd': Aucun fichier ou dossier de ce type
Alors que les autres commandes fonctionnent :
ls /usr/bin/cd
ls: impossible d'accéder à '/usr/bin/cd': Aucun fichier ou dossier de ce type
Utiles
Il est possible que certaines de ces commandes n'existent pas chez vous. Installez-les.
Retour d'une commande
Lorsqu'une commande unix ne rend aucun retour visible, c'est que tout s'est bien passé.
Chaque commande va rendre un entier, appelé code de sortie, par défaut invisible sur la ligne de commande. Cet entier vaut :
- 0 si tout s'est bien passé
- un entier strictement positif s'il y a une une erreur (l'entier caractérise l'erreur)
La valeur de retour de la dernière commande exécutée dans le shell est stockée dans la variable spéciale $?
Quel est le retour de ls /
? Et de ls /root
?
Que signifie ces retours ?
solution
solution
Une fois la commande exécutée, on tape echo $?
pour connaître son code de sortie.
ls /
rend 0ls /root
rend 2 (si on a pas exécuté la commande en temps que root bien sur)
Le code de retour est déterminé dans le manuel.
On peut utiliser ce mécanisme en utilisant les opérateurs logiques &&
et ||
:
- ET logique :
commande1 && commande2
: lacommande2
ne sera exécutée que si le code de sortie de lacommande1
est un succès (vaut 0) - OU logique :
commande1 || commande2
: lacommande2
ne sera exécutée que si le code de sortie de lacommande1
est un échec (vaut >0)
En shell, 0 vaut pour un succès et le reste est un échec. Ainsi, La commande true
rend 0 et false
rend 1.
Ceci diffère de la programmation classique où 0 vaut faux et le reste vaut vrai.
Ceci permet de chaîner conditionnellement des commandes.
Quelle est la différence entre :
cd ~/truc ; touch toto
cd ~/truc && touch toto
solution
solution
Le premier va créer un fichier toto
dans truc s'il existe ou dans le répertoire courant sinon, le second crée le fichier toto dans truc s'il existe.
Que fait :
ls ~/truc || mkdir ~/truc ; cd ~/truc
solution
solution
Ca créer le dossier ~/truc
s'il n'existe pas. Puis aller dans le dossier ~/truc
Si truc existe et est un fichier. Il va cependant y avoir un soucis...
Grouper des commandes
On peut grouper de commandes de deux façons :
{ cmd1; cmd2; }
: les commandes sont exécutées dans le shell courant(cmd1 ; cmd2 ; ...)
: un shell enfant est crée pour exécuter les commandes dans la parenthèse. Ceci permet d'isoler ces exécutions
Notez que c'est bien l'accolade qui est début et la fin de l'instruction de groupement, il faut les prendre comme des commandes spéciales :
- il faut faire suivre l'accolade ouvrante d'un espace
- il faut faire précéder l'accolade fermante d'un point-virgule
Quelle est la différence entre les deux instructions suivantes :
cd /; { ls; cd; }
cd /; ( ls; cd; )
solution
solution
On ne conserve pas les dossiers courants dans un sous-shell. ON est donc toujours dans /
à la fin du second jeu d'instructions.
La création d'un shell enfant pour exécuter des commandes est un principe fondamental en unix. Il permet de compartimenter les exécutions de commandes comme on la vue dans l'exercice précédent.
Interactions avec le shell
Le shell va interpréter certains caractères, nommé métacaractères avant même que la commande ne soit exécuté. Vous en connaissez déjà au moins deux, l'espace qui sépare les arguments d'une commande et $?
, mais il en existe une foules d'autres. Parmi eux, les plus courant sont :
- l'espace pour séparer les arguments
- toute une série commençant par
$
:$?
: le code de sortie de la dernière commande$$
: le PID du shell courant$(expression)
: pour exécuter l'expression et donner son affichage comme argument. Par exempleecho $(expr 3 + 4)
. C'est bien ce qui est affiché qui est rendu, pas son code de sortie.$((arithmétique))
: pour exécuter des opérations arithmétiques, par exempleecho $((3+4))
${variable}
: pour afficher le contenu d'une variable, par exempleecho ${PAH}
- expression régulières pour les fichiers du dossiers courant (la fin de la vidéo introductive y est consacrée)
*
:echo .*
va afficher tous les fichier du dossier courant commençant par un.
. Notez bien que ce remplacement est effectué avant l'exécution deecho
qui ne voit qu'une suite de paramètres?
: un caractère. Par exemplecd ~; echo Vid?os
[caractères]
un caractère parmi la liste. Par exemplecd ~; echo [vV]id?os
On peut inhiber cette interférence du shell dans nos commandes de trois façons :
- par un
\
pour inhiber le métacaractère qui suit. Par exempleecho \*
. Attention ne marche pas si le métacaractère est composé de deux caractères, par exempleecho \$(expr 3 + 4)
ne fonctionne pas car la parenthèse n'est pas inhibée. - par des
' '
qui inhibent tous les métacaractères. Par exempleecho 'bonjour !'
ouecho '$?'
- par des
" "
qui inhibent tous les métacaractères sauf ceux commençant par$
. Par exempleecho "bonjour !"
ouecho "$?"
Vous verrez parfois `commandes`, qui est équivalent à $(commandes)
.
Par exemple :
echo `expr 3 + 4`
Qui est équivalent à :
echo $(expr 3 + 4)
J'ai tendance à préférer cette dernière notation qui est selon moi plus clair. On a déjà assez à faire avec "
et '
I/O
TBD en faire plus. Car les
|
,>
et>>
c'est pas clair.
Toute commande à 3 flux qui lui sont connectés :
- l'entrée standard, stdin, qui est par défaut le clavier
- la sortie standard, stdout, qui est par défaut l'écran
- l'erreur standard, stderr, qui est par défaut l'écran
stdin -> process --> stdout
\
-> stderr
Lecture de l'entrée standard
wc
Il lit l'entrée standard. Stopper la commande avec ctrl+C arrêter tout et interrompt la commande. Il faut terminer l'entrée standard en lui faisant lire la séquence de contrôle EOF ctrl+D.
Redirection de la sortie vers une autre commande
Commande
La redirection de la sortie vers l'entrée se fait via le pipe : |
.
TBD expliciter les commandes ci-dessous.
Le très utilisé :
cat /etc/passwd | less
Ou plus compliqué :
cat /etc/passwd | cut -d : -f 1 | lolcat
Pipe et tee
TBD créer ses propres pipe avec
mkfifo
TBD faire mieux. Mettre dans une partie à part. Un peu comme un cheveux sur la soupe là. TBD dire que la sortie de l'un va dans l'autre.
----> stdin |pipe| stdout ---->
Une seule sortie mais l'entrée peut venir de plusieurs endroits par des redirections :
-
\
----> stdin |pipe| stdout ---->
/
-
Un tee permet d'avoir 2 sorties, stdout et une sortie vers un fichier
----> stdin |pipe| stdout ---->
\
-> fichier
redirection de la sortie vers un fichier
Commande
La redirection de la sortie vers un nouveau fichier se fait avec : >
.
echo "toto" > truc
Commande
La redirection de la sortie vers la fin d'un fichier existant se fait avec : >>
.
echo "toto" >> truc
Redirection de l'erreur
ls /truc 2>&1 | lolcat
tee pour :
- sauver un résultat intermédiaire dans une chaîne
- sauver et voir le stdout
car particulier de l'affichage à l'écran
Souvent les commandes savent si leur stdout est dirigé vers un terminal (doit être affiché à l'écran) ou un fichier, et vont se comporter différemment selon le cas.
Par exemple va lister les fichier les uns à la suite ds autres pour une sortie écran et un par ligne pour une sortie fichier ou pipe
$ ls
Bureau Images Musique snap temp truc
Documents Modèles Public Téléchargements test Vidéos
$ ls > ls.result
$ cat ls.result
Bureau
Documents
Images
ls.result
Modèles
Musique
Public
snap
Téléchargements
temp
test
truc
Vidéos
Si on "voir" ce qui se passe si on redirige vers un fichier, on peut rediriger vers cat
:
$ ls | cat
Bureau
Documents
Images
ls.result
Modèles
Musique
Public
snap
Téléchargements
temp
test
truc
Vidéos
Exercice
TBD en faire des petits commandes à suivre.
On aura besoin de tout ce qu'on a appris
hexdump -C < /dev/random
xxd < /dev/random
base64 </dev/random | head -c 100
base64 </dev/random 2>/dev/null | head -c 100
base64 </dev/random | head -c 100 ; echo
echo "hasard : "$(base64 </dev/random 2>/dev/null| head -c 100)