Sites


Introduction à la ligne de commande

CommandLineIntro: CommandHistory

Raccourcis et historiques de commandes

Le shell permet de rappeler des commandes entrées précédemment et de les exécuter à nouveau, après les avoir éditer si nécessaire. C'est une des manières les plus simples et efficaces de réduire le nombre de caractères tapés, car répéter des séquences de commandes est très fréquent. Par exemple, dans la séquence ci-après nous allons dans différents répertoires, listant leur contenu, détruisant les fichiers que nous ne désirons plus et sauvant certains autres fichiers sous d'autres noms :

cd Pictures/                              
ls -l status.log.*
rm status.log.[3-5]
mv status.log.1 status.log.bak

cd ../Documents/
ls -l status.log*                                                            
rm status.log.[2-4]
mv status.log.1 status.log.bak

cd ../Videos/
ls -l status.log*
rm status.log.[2-5]
mv status.log.1 status.log.bak

Si vous deviez faire ce genre de nettoyage régulièrement, vous termineriez par écrire un script pour l'automatiser et vous l'exécuteriez peut-être à intervalles réguliers en utilisant une tâche cron. Mais pour le moment, contentons-nous de voir à quel point le nombre de caractères tapés peut être réduit lorsque les commandes sont entrées manuellement.

Dans un chapitre précédant, nous avons vu comment utiliser les touches flèches pour ce déplacer dans l'historique des commandes comme si vous étiez en train d'éditer un fichier. Ce chapitre expose une autre façon de manipuler l'historique à la fois plus compliquée et plus ancienne. Vous trouverez parfois les méthodes décrites ici comme étant cependant plus facile à mettre en oeuvre, cela vaut donc la peine de les pratiquer. Supposons par exemple, que vous vous rappelez avoir exécuté la commande mv dont vous avez besoin une heure plus tôt (ou une autre commande similaire). Utiliser la flèche vers le haut de manière répétitive est plus compliqué que d'utiliser la technique décrite ici.

Rappeler une commande en utilisant une chaîne de caractères 

L'opérateur bang, nommé d'après le caractère ! (le point d'exclamation appelé familièrement  "bang" en anglais), vous permet de répéter les commandes récentes de votre historique.

!chaîne de caractères exécute la commande la plus récente qui commence par chaîne de caractères. Ainsi pour exécuter exactement la même commande mv que précédemment, entrez:

!mv

Que faire si vous ne voulez pas exactement la même commande? Si vous désirez appliquer une légère modification avant de l'exécuter à nouveau? Ou si vous désirez juste voir ce que l'opérateur bang retrouve dans l'historique pour vous assurez que c'est bien cette commande que vous désirez ? Vous pouvez retrouver cette commande sans l'exécuter en ajoutant  :p (for "print": imprimer):

!mv:p

Nous vous montrerons bientôt comment éditer les commandes.

Vous avez peut-être lancé plusieurs commandes mv, mais vous vous souvenez qu'il y a une chaîne de caractères unique au milieu de la commande que vous désirez exécuter à nouveau. Entourez alors la chaîne en question avec des caractères ?, comme ceci:

!?log?

Entrer deux bangs à la suite l'une de l'autre répète la dernière commande exécutée. Un truc très utile est de répéter la dernière commande avec les privilèges super-utilisateur :

sudo !!
Il nous arrive tous de temps en temps de lancer des commandes sans avoir les permissions correctes.

Si répéter la dernière commande peut vous sembler d'une utilité limitée,  cette méthode peut être adaptée, comme nous le verrons plus loin, afin de ne sélectionner que des morceaux de la dernière commande.

Rappeler une commande par numéro

Le shell numérote dans l'ordre chaque commande lancée.  Si vous désirez rappeler les commandes par numéro d'ordre, vous devrez modifier votre invite pour inclure le numéro d'ordre courant  (un chapitre ultérieur expliquera comment faire). Il est aussi possible d'obtenir la list des commandes avec leur numéro d'ordre en utilisant la commande history :

$ history                                                       
...
  502  cd Pictures/
  503  ls -l status.log*
  504  rm status.log.[3-5]
  505  mv status.log.1 status.log.bak
  506  cd ../Documents/
  507  history                                      
$

Nous n'avons montré ici que les dernières lignes imprimées.  Si vous désirez répéter la commande rm la plus récente (commande numéro 504), c'est possible en tapant :

!504

Les numéro d'ordre sont probablement plus utiles en comptant à rebours. Si, par exemple, vous vous souvenez que vous avez exécuté la commande rm suivie de trois commandes, rm peut être exécuter à nouveau en tapant :

!-4

Ceci dit au shell, "à partir d'où je suis maintenant, compte à rebours quatre commandes, et exécute la commande à cette endroit dans l'historique".

Réutiliser les arguments

Fréquemment vous désirerez réutiliser certains fragments d'une commande exécutée, soit parce que vous avez fait une erreur de frappe, ou encore parce que vous exécutez une séquence de commandes afin de réaliser une tâche particulière.  Il est possible de faire cela en utilisant l'opérateur bang avec des modificateurs.

Les trois modificateurs les plus utiles sont : *, !^, et !$, qui sont respectivement les raccourcis pour tous les arguments, le premier et le dernier argument. Étudions les dans cet ordre.

"nomDeCommande *" exécute nomDeCommande avec les arguments que vous avez utilisé avec la dernière commande entrée. Ceci peut être utile si vous avez fait une erreur de frappe. Par exemple, si vous avez tapé emasc au lieu de emacs:

emasc /home/fred/mywork.java /tmp/testme.java

Cela va évidemment échouer. Ce que vous pouvez alors faire est taper :

emacs !*

Ceci exécute emacs avec les arguments que vous venez juste de taper à la ligne de commande. Ce qui est équivalent à taper :

emacs /home/fred/mywork.java /tmp/testme.java

"nomDeCommande !^" répète le premier argument.

emacs /home/fred/mywork.java /tmp/testme.java
svn commit !^    # equivalent to: svn commit /home/fred/mywork.java

"nomDeCommande !$" répète le dernier argument.

mv /home/fred/downloads/sample_screen_config /home/fred/.screenrc
emacs !$     # equivalent to: emacs /home/fred/.screenrc

Vous pouvez aussi utiliser ces deux raccourcis en même temps. Imaginons que vous ayez entré :

mv mywork.java mywork.java.backup
alors qu'en fait vous vouliez faire une copie. Vous pouvez rectifier cette erreur en exécutant:
cp mywork.java.backup mywork.java

Comme vous réutilisez les arguments dans l'ordre opposé, un raccourcis utile pourrait être :

cp !$ !^

Pour un contrôle plus précis des arguments, vous pouvez utiliser un double bang avec le modificateur  :N afin de sélectionner le Nième argument.  C'est très utile lorsque vous utilisez une commande avec sudo, car votre commande originale devient le premier argument. L'exemple ci-dessous illustre comment faire.

sudo cp /etc/apache2/sites-available/siteconfig /home/fred/siteconfig.bak
echo !^ !!:2  # equivalent to echo cp /etc/apache2/sites-available/siteconfig

Il est aussi possible de spécifier une plage d'arguments avec !!:M-N.

Modifier les arguments

Souvent vous voudrez exécuter à nouveau une commande en en changeant néanmoins une partie. Supposons, par exemple, que vous exécuter une commande sur file1 :

$ wc file1
     443    1578    9800 file1

Vous désirez maintenant supprimer file2, qui a un nom très proche de file1. Vous pouvez utiliser le dernier paramètre de la commande précédente avec "!$", mais en le modifiant de la manière suivante :

$ rm !$:s/1/2/                                    
rm file2

Voilà qui parait relativement compliqué, regardons donc les différentes parties de l'argument :

!$   :   s/1/2/

Le raccourci "!$" est suivi d'un double point et de la commande "s", signifiant "substitute". Ensuite il y a la chaîne que vous désirez remplacer (1) et la chaîne que vous voulez mettre à sa place (2) le tout séparé par des barres obliques. Le shell imprime la commande telle qu'il a interprété votre entrée et l'exécute.

Ce genre de substitutions est tellement commun, que vous serez content d'apprendre qu'il existe un moyen bien plus simple d'exécuter une commande avec des modifications mineures. Il est possible de changer seulement une chaîne dans la commande avec la syntaxe suivante :

$ wc file1                                                   
     443    1578    9800 file1
$ ^1^2                                        
wc file2

Nous avons introduit un caret (^), la chaîne que nous voulions remplacer, un autre caret, et la chaîne que vous désirerions mettre à sa place.

Chercher dans l'historique de commandes

Utilisez la combinaison de touches Ctrl + R pour effectuer une recherche dans les commandes précédentes ("reverse-i-search"). Par exemple, si vous voulez utiliser la commande tapée la dernière fois que vous avez lancé snort, commencez par taper  Ctrl + R. Le terminal indiquera :

(reverse-i-search)`':

Alors que vous tapez chaque lettre (s, n, etc.) le shell affiche la commande la plus récente qui contient la chaîne.  Lorsque vous avez tapé "snort", vous pouvez répéter Ctrl + R pour rechercher (de la plus récente à la plus ancienne) dans toutes les commandes contenant la chaîne "snort." Lorsque vous avez trouvé la commande que vous cherchiez, les touches flèches gauche et droite vous permettent d'éditer la commande tandis que Enter lancera son exécution.

Partager l'historique de bash

Le shell bash sauvegarde votre historique afin que vous puissiez exécuter à nouveau des commandes tapées lors de sessions précédentes. Cependant, l'historique n'est sauvé que lorsque vous fermez le terminal. Cela implique que, s'il vous arrive de travailler avec deux terminaux simultanément, vous ne pourrez pas partager les commandes.

Pour résoudre ce problème (ou que vous désirez que le terminal sauvegarde chaque commande immédiatement après son exécution)  ajoutez les lignes suivantes à votre fichier ~/.bashrc :

shopt -s histappend
PROMPT_COMMAND='history -a'

L'utilisation des raccourcis décrits dans ce chapitre vous permettra d'économiser énormément de temps... donc expérimentez!

Il y a une erreur de communication avec le serveur Booktype. Nous ne savons pas actuellement où est le problème.

Vous devriez rafraîchir la page.