Une commande externe est un fichier présent dans l'arborescence.
Quand un utilisateur exécute la commande ls, le shell demande au noyau Linux d'exécuter le fichier /bin/ls
Sont considérés comme commandes externes, tous les fichiers au format binaire exécutable ainsi que tous les fichiers au format texte représentant un script de commandes.
La commande file indique le type de données contenues dans un fichier.
$ file /bin/ls
/bin/ls: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped
$ file monscript
monscript: POSIX shell script text executable
L'argument de la commande file est un nom de fichier indiqué en relatif ou en absolu
Une commande interne est intégrée au processus shell.
Elle n'a aucune correspondance avec un fichier sur le disque.
La commande type indique si une commande est interne ou externe.
$ type cd
cd est une primitive du shell
$ type ls
ls est un alias vers « ls --color=auto »
La commande type prend en argument le nom d'une commande. Si cette dernière n'est pas une commande interne, elle est recherchée dans les répertoires indiqués dans la variable PATH
Certaines commandes ont une implémentation interne et externe.
La commande pwd est une commande interne :
$ type pwd
pwd est une primitive du shell
La commande pwd possède également une implémentation externe :
$ ls -l /bin/pwd
-rwxr-xr-x 1 root root 34376 2010-09-21 20:33 /bin/pwd
Pour forcer l'utilisation de la commande externe, il faut indiquer l'emplacement de la commande :
$ /bin/pwd
/home
$ cd /bin
$ ./pwd
/bin
La commande interne echo permet d'afficher des données à l'écran.
$ echo Ceci est un exemple
Ceci est un exemple
Il faut échapper l'apostrophe avec l'antislash
$ echo Un exemple avec l\'apostrophe
Un exemple avec l'apostrophe
Il faut échapper les guillemets avec l'antislash
$ echo Un exemple avec des \"guillemets\"
Un exemple avec des "guillemets"
En bash, il faut obligatoirement utilisé l'option "-e" pour utiliser les caractères spéciaux suivants.
$ echo -e "Un exemple\navec un saut de ligne"
Un exemple
avec un saut de ligne
Sans le caractère "\c"
$ echo -e "Une ligne" ; echo -e "Une autre ligne"
Une ligne
Une autre ligne
Avec le caractère "\c"
$ echo -e "Une ligne\c" ; echo -e "Une autre ligne"
Une ligneUne autre ligne
L'option -n remplace le caractère "\c"
$ echo -n "Une ligne" ; echo "Une autre ligne"
Une ligneUne autre ligne
$ echo -e "Voici 1 tabulation\tet la suite"
Voici 1 tabulation et la suite
$ echo -e "Afficher un antislash\\"
Afficher un antislash\
Liste des caractères spéciaux :
\0NNN | Valeur d'un caractère exprimé en octal |
\\ | Antislash |
\a | Bip |
\b | Effacement du caractère précédent |
\c | Suppression du saut de ligne en fin de ligne |
\f | Saut de page |
\n | Saut de ligne |
\r | Retour chariot |
\t | Tabulation horizontale |
\v | Tabulation verticale |
Le caractère "~" représente le répertoire HOME de l'utilisateur.
Par exemple, pour l'utilisateur "toto"
$ cd ~
$ pwd
/home/toto
Copier le fichier "fichier1" du répertoire /tmp dans le répertoire /home/toto
$ cd /tmp
$ cp fichier1 ~
Copier le fichier "fichier2" du répertoire /tmp dans le répertoire /home/toto/mesfichiers
$ cd /tmp
$ cp fichier2 ~/mesfichiers
Si le caractère "~" est immédiatement suivi d'un mot, ce dernier est considéré comme un nom d'utilisateur.
Copier le fichier "fichier3" du répertoire /home/toto vers le répertoire /home/titi
$ cd ~
$ pwd
/home/toto
$ cp fichier3 ~titi
Copier le fichier "fichier4" du répertoire /home/toto vers le répertoire /home/titi/tmp
$ cd ~
$ pwd
/home/toto
$ cp fichier4 ~titi/tmp
La commande cd, sans arguments, permet à l'utilisateur de se placer dans son répertoire HOME.
$ pwd
/tmp
$ cd
$ pwd
/home/toto
Identique en utilisant le caractère "~"
$ cd ~
Pour se rendre dans le répertoire HOME de tata :
$ pwd
/home/toto
$ cd ~tata
$ pwd
/home/tata
Pour revenir au répertoire précédent avec la commande "cd -" :
$ cd -
$ pwd
/home/toto
Attention, certaines de ces expressions ne fonctionnent pas toutes avec les mêmes shell.
Pour certaines, elles sont compatibles BASH, pour d'autres ZSH et certaines ne fonctionnent qu'avec KSH.
Le caractère "*" permet de remplacer n'importe quel caractère.
$ ls
fichier1 fichier2.a monfichier tOnfichier.b
$ ls *.a
fichier2.a
$ ls f*
fichier1 fichier2.a
Le caractère "?" représente un caractère quelconque.
$ ls *.?
fichier2.a tOnfichier.b
$ ls ????????
fichier1
Les caractères "[ ]" permettent d'indiquer la liste des caractères que l'on recherche à une position bien précise dans le noms des fichiers.
$ ls [ft]*.[a-z]
fichier2.a tOnfichier.b
% ls ?[A-Z0-9e]*
cOucou f1chier F2chier Hello
$ ls [!a-z]*
1coucou Coucou F2chier Fichier Hello
% rm -i *.b *.c
rm : supprimer fichier vide «fichier1.b» ? y
rm : supprimer fichier vide «fichier1.c» ? y
Les expressions complexes sont compatible BASH à condition d'activer l'option extglob avec la commande shopt (shopt -s extglob).
$ ls
1coucou coucou.t fichier159159159.log fichier161.log fichier.log
cOucou coucou.uvw fichier159159.log fichier1.a Hello.txt
Coucou f1chier fichier159160.log fichier1.abc
coucou.r F2chier fichier159.log fichier1.b
coucou.s Fichier fichier160.log fichier1.c
L'expression sera présente 0 ou 1 fois.
Afficher tous les fichiers dont le nom contient 0 ou 1 fois "159"
$ ls fichier?(159).log
fichier159.log fichier.log
L'expression sera présente entre 0 et x fois.
Afficher tous les fichiers dont le nom contient 0 ou x fois "159"
$ ls fichier*(159).log
fichier159159159.log fichier159159.log fichier159.log fichier.log
L'expression sera présente entre 1 et x fois.
Afficher tous les fichiers dont le nom contient 1 ou x fois "159"
$ ls fichier+(159).log
fichier159159159.log fichier159159.log fichier159.log
L'expression sera présente exactement 1 fois.
Afficher tous les fichiers dont le nom contient 1 fois "159"
$ ls fichier@(159).log
fichier159.log
L'expression ne sera pas présente.
Afficher tous les fichiers dont le nom ne contient pas 1 fois "159"
$ ls fichier!(159).log
fichier159159159.log fichier159160.log fichier161.log
fichier159159.log fichier160.log fichier.log
Afficher tous les fichiers dont le nom ne contient pas "fichier"
$ ls !(fichier*)
1coucou Coucou coucou.s coucou.uvw F2chier Hello.txt
cOucou coucou.r coucou.t f1chier Fichier
Une barre verticale dans une expression correspond à "ou bien"
Afficher tous les fichiers dont le nom contient 1 fois "159" ou "160"
$ ls fichier@(159|160).log
fichier159.log fichier160.log
Afficher tous les fichiers dont le nom contient 1 ou x fois "159" ou "161"
$ ls fichier+(159|161).log
fichier159159159.log fichier159159.log fichier159.log fichier161.log
Afficher tous les fichiers dont le nom contient 1 fois ( 1 ou x fois "159" ou "161")
$ ls fichier@(+(159)|+(161)).log
fichier159159159.log fichier159159.log fichier159.log fichier161.log
Le caractère ";" permet d'écrire plusieurs commandes sur une même ligne. Toutes les commandes sont exécutées dans l'ordre.
$ pwd
/home/toto
$ ls
1coucou coucou.t fichier159159159.log fichier161.log fichier.log
cOucou coucou.uvw fichier159159.log fichier1.a Hello.txt
Coucou f1chier fichier159160.log fichier1.abc
coucou.r F2chier fichier159.log fichier1.b
coucou.s Fichier fichier160.log fichier1.c
$ mkdir tmp; chmod 755 tmp; chown toto:toto tmp; cd tmp; pwd
/home/toto/tmp
Les redirections sont souvent utilisées dans les commandes Linux.
Elles permettent de récupérer le résultat d'une ou plusieurs commandes dans un ou plusieurs fichiers ou de faire lire le contenu d'un fichier à une commande.
Les commandes Linux ont par défaut 3 descripteurs de fichier différent.
L'entrée standard d'une commande correspond au descripteur de fichier 0.
Les commandes qui attendent des informations de la part de l'utilisateur déclenche une requête de lecture sur le descripteur 0.
Par défaut, ce descripteur est associé au terminal et donc par une saisie au clavier.
La sortie standard d'une commande correspond au descripteur de fichier 1.
Le résultat d'une commande est, par défaut, affichée à l'écran via ce descripteur mais il peut être redirigé dans un fichier.
La sortie d'erreur standard d'une commande correspond au descripteur de fichier 2.
Quand une commande rencontre une erreur, celle-ci est retournée à l'écran via le descripteur 2 mais elle peut également être retournée dans un fichier.
Cette redirection permet d'écrire dans un fichier le résultat d'une commande au lieu de l'afficher à l'écran.
Simple redirection
$ commande > fichier
ou
$ commande 1> fichier
Si le fichier n'existe pas, il est automatiquement créé. S'il existe déjà, il est tout simplement écrasé.
Récupérer le résultat de la commande ls dans un fichier "liste"
$ ls > liste
$ cat liste
1coucou
cOucou
Coucou
Double redirection
Elle permet de concaténer le résultat d'une commande au contenu d'un fichier déjà existant.
$ commande >> fichier
ou
$ commande 1>> fichier
Si le fichier n'existe pas, il est automatiquement créé. S'il existe déjà, le résultat de la commande est ajouté au fichier.
$ pwd >> liste
$ cat liste
1coucou
cOucou
Coucou
/home/toto
Simple redirection
$ commande 2> fichier
$ ls /root 2> erreur
$ cat erreur
ls: impoossible d'ouvrir le répertoire /root: Permission non accordée
Double redirection
$ commande 2>> fichier
$ mkdir /root/tmp 2>> erreur
$ cat erreur
ls: impoossible d'ouvrir le répertoire /root: Permission non accordée
mkdir: impossible de créer le répertoire «/root/tmp»: Permission non accordée
Il est possible de rediriger plusieurs sorties sur une même ligne de commande.
$ commande 1> fichier1 2> fichier2
ou
$ commande 2> fichier2 1> fichier1
$ find /etc -name smb.conf 1> resultat 2> erreur
$ cat resultat
/etc/samba/smb.conf
$ cat erreur
find: "/etc/lvm/cache": Permission non accordée
find: "/etc/lvm/backup": Permission non accordée
find: "/etc/lvm/archive": Permission non accordée
Si l'on ne souhaite pas afficher et/ou enregistrer les erreurs retournées, il est possible de rediriger le descripteur 2 vers un fichier spécial existant sur tous les systèmes Linux "/dev/null"
$ find /etc -name smb.conf 1> resultat 2> /dev/null
$ cat resultat
/etc/samba/smb.conf
$ cat /dev/null
$
La redirection de l'entrée standard concerne toutes les commandes attendant une saisie de la part de l'utilisateur sur le descripteur 0 (saisie écran).
$ mail toto
>Coucou
>Comment vas tu ?
>^d (équivalent de CTRL+d)
$
La commande mail lit sur l'entrée standard toutes les données saisies à l'écran. La saisie se termine par la fonction CTRL+d.
Ensuite, la commande mail envoie ces données dans un message à l'utilisateur indiqué (toto).
Il est tout à fait possible d'écrire le contenu du message dans un fichier et de "l'injecter" à la commande mail sur son descripteur 0.
$ commande 0< fichier
ou
$ commande < fichier
$ echo "Coucou, comment vas tu ?" > message
$ cat message
Coucou, comment vas tu ?
$ mail toto < message
$ commande 1> fichier1 2>&1
ou
$ commande 2> fichier2 1>&2
Le principe consiste à écrire dans un fichier le résulat du descripteur 1 dans le fichier "fichier1" (1> fichier1) puis le résultat du descripteur 2 vers le descripteur 1 (2>&1) et par conséquent dans le fichier "fichier1".
$ find /etc -name smb.conf 1> resultat 2>&1
$ cat resultat
find: "/etc/lvm/cache": Permission non accordée
find: "/etc/lvm/backup": Permission non accordée
find: "/etc/lvm/archive": Permission non accordée
/etc/samba/smb.conf
Attention :
$ commande 2>&1 1> fichier1
Cette syntaxe n'agit pas de la même manière que les précédentes.
En effet, nous indiquons dans un premier temps de rediriger le descripteur 2 (sortie d'erreur standard) vers le descripteur 1, c'est à dire vers la sortie standard qui est, par défaut, l'affichage à l'écran, puis dans un second temps nous redirigeons le descripteur 1 (sortie standard) vers le fichier "fichier1".
En conclusion, tous les messages d'erreurs seront affichés à l'écran et le résulat de la commande dans le fichier "fichier1".
Cela revient à saisir :
$ commande 1> fichier1
Elle est principalement utilisée dans les scripts shell.
Elle permet de connecter l'entrée standard d'une commande sur une portion du script
Par exemple, avec la commande mail, cela permet de terminer la saisie du texte avec un caractère ou une chaine de caractère.
$ mail toto<<end
> bonjour
> ceci est un test
> end
$
Pour mettre fin à la commande mail, il suffit simplement de saisir l'expression inscrite juste après les doubles chevrons "<<". Dans l'exemple, la commande se termine après avoir saisi "end".
Identique à la fonction ^d (CTRL+d) en console.
Utilisation dans un script :
$ cat envoiMail.sh
#!/bin/sh
mail toto<<end
Bonjour,
Ceci est un test
Voici la liste des fichiers presents dans ton repertoire :
`ls -lhtr`
end
exit 0
Exécution du script
$ sh ./envoiMail.sh
Il est tout à fait possible de fermé un descripteur d'entrée ou de sortie en utilisant les symboles "<&-" ou ">&-" ou "2>&-".
Descripteur d'entrée standard "0" :
$ commande <&-
Descripteur de sortie standard "1" :
$ commande >&-
Descripteur de sortie d'erreur standard "2" :
$ commande 2>&-
Un tube de communication, ou pipe en anglais, permet de faire communiquer 2 commandes.
Ce "tube" est représenté par la barre verticale "|".
Le résultat de la commande de gauche est envoyé dans le tube et récupéré par la commande de droite.
C'est à dirte que la sortie standard "1" de la commande de gauche est connecté directement à l'entrée standard "0" de la commande de droite.
La sortie d'erreur standard "2" de la commande de gauche n'est pas envoyée dans le tube.
Pour que cette utilisation est un sens il faut impérativement que la commande de gauche utilise la sortie standard "1" et que la commande de droite utilise l'entrée standard "0".
Les commandes lisant leur entrée standard sont facilement identifiable car elles demandent une saisie au clavier.
Envoyer par mail la liste des users connectés :
$ who | mail toto
Envoyer par mail la liste des fichiers d'un répertoire :
$ ls -lht | mail toto
Envoyer un message à un utilisateur connecté au système :
$ echo "coucou, comment vas tu ?" | write tata
Afficher le nombre de fichiers d'un répertoire :
$ ls | wc -l
29
Envoyer par mail le nombre de fichiers d'un répertoire :
$ ls | wc -l | mail toto
Afficher avec pagination le contenu d'un fichier :
$ cat /etc/passwd | more
Lister le contenu d'un répertoire avec pagination :
$ ls -lht /etc | more
Afficher uniquement certains éléments d'un fichier :
$ cat /etc/passwd | grep root | cut -d':' -f1,7
root:/bin/bash
Envoyer par mail certains éléments d'un fichier :
$ cat /etc/passwd | grep root | cut -d':' -f1,7 | mail toto
Afficher à l'écran et enregistrer dans un fichier le contenu d'un répertoire :
$ ls -t | tee listeFichiers
listeFichiers
envoiMail.sh
message
script.sh
$ cat listeFichiers
listeFichiers
envoiMail.sh
message
script.sh
Il est donc tout à fait possible de cumuler autant de commandes que l'on souhaite à partir du moment où l'on respecte l'ordre des commandes et des sorties / entrées standard.
$ ls -l /root 2>&1 | tee listeFichiers
ls: impoossible d'ouvrir le répertoire /root: Permission non accordée
$ cat listeFichiers
ls: impoossible d'ouvrir le répertoire /root: Permission non accordée
Le regroupement de commandes est utilisé pour rediriger les sorties standards de plusieurs commandes vers un même fichier ou vers un tube ou pour exécuter des commandes dans un même environnement.
$ date ; ls > listeFichiers
lundi 19 septembre 2011, 08:47:11 (UTC+0200)
$ cat listeFichiers
1coucou
cOucou
Coucou
coucou.r
coucou.s
coucou.t
coucou.uvw
envoiMail.sh
Dans l'exemple ci-dessus, la commande date et ls sont regroupées grâce au caractère ";".
Le résultat de la commande date est affiché à l'écran alors que le résultat de la commande ls est redirigé dans le fichier "listeFichiers".
Afin de rediriger la sortie standard des 2 commandes au même endroit, ils faut obligatoirement les regroupées avec des parenthèses "()" ou des accolades "{}".
$ ( date ; ls ) > listeFichiers
$ cat listeFichiers
lundi 19 septembre 2011, 08:51:58 (UTC+0200)
1coucou
cOucou
Coucou
coucou.r
coucou.s
coucou.t
coucou.uvw
envoiMail.sh
Les commandes regroupées entre parenthèses sont exécutées par le shell enfant alors que les commandes regroupées entre accolades sont exécutées par le shell parent.
Regroupement avec parenthèses :
$ pwd
/home/toto
$ ( mkdir temp ; cd temp ; touch fichierTemp ; pwd ; ls ) > listeFichiers
$ cat listeFichiers
/home/toto/temp
fichierTemp
$ pwd
/home/toto
Après exécution des commandes, le répertoire courant est le même qu'avant exécution.
Regroupement avec accolades :
$ pwd
/home/toto
$ { mkdir temp ; cd temp ; touch fichierTemp ; pwd ; ls ; } > listeFichiers
$ pwd
/home/toto/temp
$ cat ../listeFichiers
/home/toto/temp
fichierTemp
Après exécution des commandes, le répertoire courant n'est plus le même qu'avant exécution.
Généralement, le regroupement entre parenthèses est plus utilisé que le regroupement entre accolades car la syntaxe est plus simple et cela ne modifie pas le shell courant mais pour un gain de performances le regroupement entre accolades est préférable.
Pour exécuter des commandes en arrière-plan, il suffit de rajouter à la fin le caractère "&".
Cela permet de récupérer le shell aussitôt après sans être obligé d'attendre la fin de l'exécution de la commande précédente.
Par contre, il est préférable d'utiliser la redirection de la sortie standard et de la sortie d'erreur standard.
$ find /etc -name passwd 1>listePasswd 2>/dev/null &
$ echo "On peut saisir d'autre commandes en attendant de voir le message ci-dessous une fois le processus terminé"
[1]+ Exit 1 find /etc -name passwd > listePasswd 2> /dev/null
$ cat listePasswd
/etc/passwd
/etc/webmin/passwd
/etc/pam.d/passwd