Le 1998-07-09 Olivier Rossel écrivait dans la liste de diffusion Linux-31
> Comment dans Unix avoir la liste de TOUTES les commandes que l'on peut > lancer? > Par exemple, si je tape a puis TAB depuis un shell style tcsh ou bash, > j'aurai la liste de toutes les commandes commencant par a, > idem pour b etc... > Y a t il un moyen de systematiser cela pour a la fin avoir un beau > fichier texte qui recapitule toutes les commandes disponibles?
Profitons de l'occasion pour comparer les solutions a ce probleme avec differents langages de script. Cela permettra de se donner une goût de ce que sont ces différents langages.
Le shell est le langage de script de référence. C'est le seul qu'on peut être certain de retrouver sur n'importe quelle machine Unix, ce qui explique que les scripts de démarrage (dans /etc/rc.d/) soient écrits en shell. Gregory Kurz propose la méthode suivante:
#!/bin/sh IFS=':' for d in $PATH; do for f in $d/*; do [ -x $f -a ! -d $f ] && echo $f done done
What is the sound of Perl? Is it not the sound of a wall that people have stopped banging their head against?-- Larry Wall
Perl est un langage de script très puissant (avec des extensions orientées objet et de puissantes fonctionalités de traitement de chaines et d'expressions régulières). Il est largement utilisé pour écrire des scripts CGI et même pour des applications plus importantes tel que Majordomo. Il existe une très importante bibliothèque de fonctions Perl permettant de faire du ftp, d'envoyer des email, de lire des fichiers gzippés ou des archives tar, par exemple.
#!/usr/local/bin/perl for (split(/:/, $ENV{'PATH'})) { opendir(DIR, $_) or die "can't opendir $_: $!"; grep {!/^\./ && print "$_\n" } readdir(DIR); closedir DIR; }
Python est un langage de script très propre et bien conçu, avec des notions d'orientation objet. Tout comme Perl, il bénéficie d'une vaste bibliothèque de fonctions utiles. Il est mieux adapté que Perl aux problèmes de taille relativement importante, grâce à son système de modules et à la plus grande rigueur du langage. Stephane Fermigier propose la solution suivante (notez que le Python est assez original en ce que l'indentation du code détermine son sens) :
#!/usr/local/bin/python import os, string, stat for d in string.split(os.environ['PATH'], ':'): for f in os.listdir(d): mode = os.lstat(d + '/' + f)[stat.ST_MODE] if not stat.S_ISDIR(mode): print f
Scheme est un langage de programmation dérivé de la famille Lisp. C'est un langage fonctionnel très élégant et propre. Le projet GNU a choisi d'utiliser un dérivé de Scheme, Guile en tant que langage d'extension officiel; le logiciel de traitement d'image The Gimp incorpore Guile, et on peut s'en servir pour écrire des modules d'extension. Le très populaire éditeur Emacs incorpore également un langage d'extension similaire à Scheme. Scheme proprement dit ne comporte pas de primitives permettant la programmation système, mais des implémentations tel que Scsh pallient à ce manque.
Solution proposée par Eric Marsden, en Scsh:
#!/usr/local/bin/scsh -s !# (map (lambda (f) (display f) (newline)) (apply append (map directory-files ((infix-splitter ":") (getenv "PATH")))))
Explication de texte:
'("/usr/local/bin" "/bin" "/usr/bin" "/usr/X11R6/bin" "/usr/local/pgsql/bin" "/home/ecm/bin" "/usr/local/jdk/bin")
(append '("un" "deux" "trois") '(1 2 3)) -> '("un" "deux" "trois" 1 2 3)
(map (lambda (x) (* x 7)) '(6 7 8)) -> '(42 49 56)
Olivier Rossel ne se laisse pas faire et presente sa version avec Vim et des redirections sauvages dans des fichiers.
Et voila! C'etait la solution avec Vi ou sed...
Bon, on constate comme dirait Larry Wall que ``There's more than one way to do it''.
On déborde du cadre strict des langages de script, mais Emacs est un éditeur remarquable pour son langage d'extension, un dialecte du Lisp, dans lequel est programmé l'essentiel des fonctionalités de l'éditeur. Les utilisateurs passionnés s'en servent pour beaucoup de tâches que d'autres Unixiens résoudraient avec des langages de script. Notons enfin que Emacs peut être invoqué avec l'option -batch, qui le permet de servir d'interpréteur de scripts Emacs Lisp. Voici la solution proposée par Eric Marsden (on peut rentrer ce code dans le buffer *scratch*, qui est créé au lancement de Emacs) :
(append (mapcar #'directory-files (dired-split ":" (getenv "PATH"))))
Il manque encore des langages de script bien connus, tels que Tcl. Y'a des volontaires?
Si avez d'autres liens interessants, en français peut-être, n'hésitez pas à nous contacter.