
A cause d'une limite au nombre de caractères d'un article, j'ai du le couper en deux, la deuxième partie est par ici
1 - Introduction
Il est fréquent quand on fait un minimum de programmation d'avoir recours à des outils en ligne de commande ou de devoir comprendre des instructions un peu cryptiques qui parlent de "terminal", "shell" ou que sais-je encore. Pour pouvoir s'en sortir, un minimum d'explication est nécessaire, c'est ce que je vais essayer de vous fournir dans cet article.
"Terminal" vous dites?
Un petit peu d'histoire avant tout. Mac OS X est "basé sur Unix", tout le monde comprend vaguement que "Unix" c'est un système d'exploitation (par extension, une famille de systèmes d'exploitation qui en découlent) vieux comme le monde ou presque (35 ans ce n'est pas rien en informatique) et qui est synonyme de fiabilité et de solidité. Plongeons donc un peu dans le passé, il y a une quarantaine d'années les ordinateurs étaient loin d'être personnels et occupaient souvent une pièce entière à eux seuls. A un ordinateur était relié une "console" réservée à l'opérateur, et un certain nombre de "terminaux" où les différents utilisateurs entraient leurs programmes, en demandaient l'exécution, et obtenaient les résultats. Ce vocable est resté, même si actuellement la console et les terminaux sont sur une même machine, on parle d'ailleurs plus exactement d'émulateurs de terminaux. D'ailleurs on utilise plus fréquemment un shell graphique qu'un shell en ligne de commande.
Un "shell" vous dites?
Entre un utilisateur et un ordinateur il faut un logiciel qui obtienne des ordres de l'utilisateur, les comprenne, les exécute en faisant le plus souvent appel à d'autres programmes, et indique à l'utilisateur quel est le résultat de ses ordres. Un tel interprête de commandes, ou "shell" dans le jargon, peut se présenter de deux manières principales; en ligne de commande ou en graphique.
Un shell graphique vous connaissez, les environnements qui vous présentent des menus, des icônes, des fenêtres... sont des shells graphiques. Vous utilisez la souris pour donner des instructions via les icônes, boutons, ou menuset ces instructions sont exécutées. Dans le Finder, par exemple, un double-clic sur l'icône représentant une application va demander l'exécution de celle-ci, et le glisser-déposer de l'icône d'un document sur celle d'une application va demander l'ouverture du document indiqué par l'application indiquée. C'est finalement tellement intuitif et habituel qu'on en oublie ce que c'est.
Un shell en ligne de commande c'est finalement la même chose, sauf qu'au lieu d'une souris, de clics et de gestuelle, c'est un clavier et des commandes écrites qu'on utilise pour indiquer à l'ordinateur quoi faire. Et là aussi, à l'usage ça devient vite tellement évident qu'on en vient à se demander pourquoi on trouvait tout ça cryptique au départ. Il existe beaucoup de shells différents, chacun avec ses forces et ses faiblesses, ici je parlerai de celui qu'utilise par défaut Mac OS X, à savoir Bash.
En route, camarade!
Eh bien allons-y, le terminal de Mac OS X se trouve à /Applications/Utilitaires/Terminal.app. Double-clic et route pour l'aventure. Vous devez obtenir une fenêtre qui ressemble à ce qui suit, pas de panique si ce n'est pas exactement ça.

Petit tour d'horizon en vitesse, outre le message de bienvenue on voit que la dernière ligne est une invite de commande (ou "prompt"), qui indique quelques informations à l'utilisateur et attend sa commande suivante. Dans l'ordre dans mon cas on voit le nom du Mac, le répertoire courant (ici abrégé "~" pour indiquer que je suis dans mon dossier d'utilisateur), l'utilisateur courant, et le curseur d'invite "$ ".
Pour faire simple, dans la suite j'abrégerai le plus souvent le prompt à sa plus simple expression "$ ". Les lignes commençant par un "$ " seront donc celles entrées par vous, les autres seront des retours.
2 - Commandes fondamentales
Commençons par le plus fondamental des usages du Finder, à savoir l'exploration de l'arborescence des fichiers. A tout moment, on se situe au sein d'un dossier, qu'on appelle "répertoire courant" (en anglais "working directory"), commençons par voir comment afficher le contenu du répertoire courant. La commande a utiliser est ls ("list"), qui a le répertoire courant comme argument par défaut:
Code:
$ ls Applications Code Downloads Movies Public Backup Desktop Library Music Sites Books Documents Misc Pictures
Code:
$ commande option(s) argument(s)
Code:
$ ls -l total 0 drwxr-xr-x 12 jkb jkb 408 Jun 3 22:48 Applications drwxr-xr-x 12 jkb jkb 408 Apr 19 17:33 Backup drwxr-xr-x 16 jkb jkb 544 Apr 1 09:43 Books drwxr-xr-x 17 jkb jkb 578 Apr 20 09:58 Code drwxr-xr-x 10 jkb jkb 340 Jun 6 00:10 Desktop drwxr-xr-x 19 jkb jkb 646 May 27 16:11 Documents drwxr-xr-x 11 jkb jkb 374 Jun 3 22:53 Downloads drwxr-xr-x 55 jkb jkb 1870 Apr 2 21:32 Library drwxr-xr-x 11 jkb jkb 374 Jun 1 00:36 Misc drwxr-xr-x 5 jkb jkb 170 Jun 3 22:50 Movies drwxr-xr-x 12 jkb jkb 408 May 31 12:43 Music drwxr-xr-x 106 jkb jkb 3604 Jun 3 22:14 Pictures drwxr-xr-x 4 jkb jkb 136 Mar 23 14:40 Public drwxr-xr-x 7 jkb jkb 238 Mar 23 14:40 Sites
Code:
$ ls Public Sites Public: Drop Box Sites: images index.html test jkbockstael.be
Code:
LS(1) BSD General Commands Manual LS(1)
NAME
ls -- list directory contents
SYNOPSIS
ls [-ABCFGHLPRTWZabcdefghiklmnopqrstuwx1] [file ...]
DESCRIPTION
For each operand that names a file of a type other than directory, ls
displays its name as well as any requested, associated information. For
each operand that names a file of type directory, ls displays the names
of files contained within that directory, as well as any requested, asso-
ciated information.
If no operands are given, the contents of the current directory are dis-
played. If more than one operand is given, non-directory operands are
displayed first; directory and non-directory operands are sorted sepa-
rately and in lexicographical order.
The following options are available:
-A List all entries except for . and ... Always set for the super-
:
Je reviendrai sur certaines options de ls plus tard. Pour l'instant, passons à cd ("change directory") qui sert à changer de répertoire courant. Dans le doute, si on veut savoir où on se trouve actuellement, pwd ("print working directory") est là pour ça.
En action, avec le prompt entier pour montrer que par défaut il affiche le répertoire courant:
Code:
leela:~ jkb$ cd Documents/ leela:~/Documents jkb$ cd Mac-Dev.fr/terminal/ leela:~/Documents/Mac-Dev.fr/terminal jkb$ pwd /Users/jkb/Documents/Mac-Dev.fr/terminal
Code:
leela:~/Documents/Mac-Dev.fr/terminal jkb$ cd .. leela:~/Documents/Mac-Dev.fr jkb$ pwd /Users/jkb/Documents/Mac-Dev.fr
Code:
leela:~/Documents/Mac-Dev.fr/ jkb$ cd leela:~ jkb$ pwd /Users/jkb
3 - Gestion de fichiers
Maintenant qu'on sait comment se deplacer, passons aux autres operations qu'on effectue habituellement via le Finder: créer des répertoires et des fichiers, les effacers, les copier et les déplacer.
Créer des répertoires se fait au moyen de la commande mkdir ("make directory"):
Code:
$ mkdir demo-macdev $ cd demo-macdev/ $ pwd /Users/jkb/demo-macdev
Code:
$ mkdir -p terminal/exemples/choses/diverses/variees $ mkdir -p aliments/fruits/pommes $ mkdir -p aliments/fruits/poires
Code:
$ touch aliments/fruits/pommes/pink_lady $ touch aliments/fruits/pommes/granny_smith $ touch aliments/fruits/poires/conference $ ls aliments/fruits/pommes/ granny_smith pink_lady
Code:
$ rmdir aliments/fruits/poires rmdir: aliments/fruits/poires: Directory not empty
Code:
$ rm aliments/fruits/pommes/granny_smith $ ls aliments/fruits/pommes/ pink_lady $ rm -r aliments/fruits/poires/ $ ls aliments/fruits/ pommes
Code:
$ touch foo.file $ cp foo.file blah.file $ ls aliments blah.file foo.file terminal $ cp terminal term cp: terminal is a directory (not copied). $ cp -r terminal term $ ls aliments blah.file foo.file term terminal
Le déplacement est plutôt intuitif aussi:
Code:
$ mkdir -p legumes/tomates $ mkdir -p patates $ ls aliments legumes patates terminal $ mv patates/ legumes/. $ mv legumes/ aliments/. $ ls aliments/ fruits legumes
Et avant que les attentifs me fassent remarquer que je n'ai pas parlé de comment renommer, constatez que "déplacer" et "renommer" c'est en fait essentiellement la même chose:
Code:
$ touch toto.file $ mv toto.file tata.file $ ls aliments foo.file term blah.file tata.file terminal
4 - Lire
Nous savons comment garder organisé l'arborescence de répertoires et de fichiers, passons à l'étape suivante: lire le contenu de fichiers. Nous disposons d'outils assez pratiques pour ce faire, que je vais illustrer sur un petit programme en Python, ce sera déjà plus concret que de manipuler une arborescence alimentaire!
Code:
$ cd code/ $ ls mastermind.py
Code:
$ cat mastermind.py
( je vous épargne les presque 200 autres lignes, ça défile vite )
print STR_MENU_MAIN
while (not usr_choice in menu_main_choices):
usr_choice = raw_input(STR_MENU_MAINPROMPT)
if (usr_choice == 'Q'):
return None
else:
menu_main_choices[usr_choice]()
usr_choice = ''
# Show "about" screen
def show_about():
print STR_ABOUT
raw_input()
# Main
if (SHOW_MENU):
menu_main()
else:
play_game()
# End
$
Code:
$ less mastermind.py
Code:
#! /usr/bin/env python # Game of Mastermind, with some niceties # Jean Karim Bockstael - jkb@jkbockstael.be # Import from random import randint # Gameplay constants CODE_LENGTH = 4 # Length of the code (1-16) CODE_COLORS = 10 # Number of different colors in the code (2-10) MAX_GUESSES = 5 # Max number of guesses to find the correct code (1-50) SHOW_MENU = True # Show main menu before playing a first game EASY_MODE = True # Braindead mode # String constants STR_GUESS_PROMPT = 'Guess' STR_WHITE_PEG = 'o' STR_BLACK_PEG = 'x' STR_EMPTY_PEG = '_' STR_OUTCOME_WIN = 'Won!' STR_OUTCOME_LOSS = 'Lost!' STR_OUTCOME_REVEAL = 'The secret code was: ' :
Code:
# TODO Foolproof this!
def get_guess_code():
tmp_guess = []
padding_spaces = ''
if (len(STR_GUESS_PROMPT) < CODE_LENGTH):
padding_spaces = " " * (CODE_LENGTH - len(STR_GUESS_PROMPT))
guess_prompt = STR_GUESS_PROMPT + padding_spaces + " : "
str_guess = raw_input(guess_prompt)
for i in range(0, CODE_LENGTH):
tmp_guess.append(int(str_guess[i]))
return tmp_guess
# Print a help message
def print_help():
print STR_HELP.format(codelength=CODE_LENGTH, codecolors=(CODE_COLORS-1), \
maxguesses=MAX_GUESSES, whitepeg=STR_WHITE_PEG, blackpeg=STR_BLACK_PEG, \
emptypeg=STR_EMPTY_PEG)
# Returns a code formatted for printing
def format_code(code):
formatted_code = ''
:
Il arrive souvent qu'on ne s'intéresse en fait qu'à ce qu'il y a au début ou à la fin d'un fichier. Pour ce faire, nous disposons de head et tail, qui respectivement affichent les premières et dernières lignes d'un fichier. Les deux disposent d'un option -n pour préciser le nombre de lignes à afficher, par défaut 10 lignes seront affichées.
Code:
$ head -n 3 mastermind.py
#! /usr/bin/env python
# Game of Mastermind, with some niceties
$ tail -n 5 mastermind.py
else:
play_game()
# End
5 - Ecrire
Nous avons vu comment lire le contenu des fichiers, il serait bon de savoir comment écrire lesdits fichiers. Même si nous sommes sur Mac, que notre plateforme de prédilection regorge d'éditeurs et d'IDE vraiment bien faits, c'est toujours un atout de connaître au moins les rudiments de quelques éditeurs en ligne de commande. Certaines situations ne permettent pas de s'en passer, quand on passe sous Linux ou BSD on aime connaître les outils locaux, et puis c'est tout simplement übercool de savoir se servir de Vim ou d'Emacs.
Nous avons à notre disposition le simple et amical nano et les deux frères ennemis vim et emacs. Il y a entre les utilisateurs de ces deux derniers une sorte de guerre de religions assez amusante, à laquelle j'éviterai de prendre part puisqu'il est un fait établi que Vim est de loin supérieur à Emacs :-p
nano est conçu dès le départ pour être simple d'utilisation et conciliant (pour la petite histoire, Nano est le clone libre de Pico, lequel est l'éditeur du client e-mail Pine), ce qui est évident dès son lancement:

Les deux dernières lignes sont un rappel des principales commandes au clavier, où le symbole ^ indique la touche "controle". Entrons un peu de texte et enregistrons-le (controle-O) sous le nom "helloworld.py":

Et puisqu'ici ce n'est qu'une introduction je ne vais pas m'étaler, mais vous signaler que l'aide est accessible via la commande controle-G. Le plus souvent on utilise nano parce qu'il le faut plus que par choix, et ce qu'il faut retenir est en permanence à l'écran. Fuyons par un prompt controle-X.
Si nano se veut simple en frôlant le simpliste, les deux autres éditeurs inclus dans Mac OS X, vim et emacs quant à eux jouent plutôt dans la catégorie des usine à gaz avec laquelle tout est possible, même préparer le café. En effet, il s'agit d'éditeurs conçus pour ne manquer de rien, et pour lesquels les années ont été synonymes de perfectionnement. Pour la petite histoire, vim et emacs sont aussi une des plus profondes guerres de religions du monde Unix, vim étant le descendant direct des plus vénérables éditeurs, emacs le symbole de la révolution du logiciel libre.
Il faut avouer que vim sait faire peur a l'ouverture, avec son bel ecran vierge et son interface modale. En fait, ce qu'il faut comprendre avant meme de lancer vim c'est que cet editeurs fonctionne en deux modes (principaux): un mode commande et un mode insertion. Comme leurs noms l'indiquent, le mode commande sert a donner une commande à l'éditeur, le mode insertion sert à taper du texte.
C'est flou? Ca va devenir clair, lançons vim en ouvrant le helloworld.py que nous venions de créer:
Code:
$ vim helloworld.py

A l'ouverture nous sommes dans le mode commande, dans lequel nous pouvous par exemple decider d'une substitution:
Code:
:3s/Nano/Vim

On bascule en mode commande en appuyant sur la touche esc, et on va enregistrer et quitter par la commande :wq ("write then quit").
C'est déroutant hein? Et pourtant on sent vite l'avantage du fonctionnement modal: les commandes n'utilisent qu'un doigt à la fois, et se situent dans la partie principale du clavier. Autrement dit, il est possible d'utiliser vim, même de façon très complexe, sans lever les mains du clavier ni solliciter sa souplesse en raccourcis extrêmes. Ajoutons à ça des conforts modernes comme la colorisation de syntaxe, l'indentation automatique, la complétion contextuelle, les écrans splittés... et vim montre vite que derrière son aspect austère se cache un outil vraiment puissant. Pour plus d'infos vous disposez de man vim, ou de la commande :help dans vim.
L'autre grand vénérable et respecté éditeur est emacs, le bébé d'un certain Richard Stallman qui a atteint le stade de demi-dieu par son combat à la tête de la FSF. Mais ceci est une autre histoire, ce qui compte c'est qu'emacs existe encore et a avec les années atteint le stade où on dit en souriant "emacs serait un très bon système d'exploitation s'il incluait un éditeur de texte correct".
Editons notre tout petit-petit programme au moyen d'emacs:
Code:
$ emacs helloworld.py

Enregistrons notre document par le raccourci ctrl-x ctrl-s et quittons par ctrl-x ctrl-c y avant que je ne rende trop flagrant que je préfère de très loin vim à emacs
L'aide d'emacs est disponible dans le logiciel via le raccourci ctrl-h ([B]ctrl-h t[B] propose même un tutoriel) et bien sur a la page man emacs.Par ici pour la deuxième partie...



|













