Le principe central d'Unix est qu'il existe plusieurs commandes simples qui peuvent être liées ensemble grâce aux pipes et aux redirections pour accomplir des tâches plus compliquées. Regardez les exemples suivants (je n'expliquerai que les plus compliqués ; pour les autres, reportez vous aux sections précédentes ou aux pages man).
ls est trop rapide et je ne peux pas lire le nom de tous
les fichiers.
$ ls | less
$ cat fichier.txt | sort -r | lpr
$ sort fichier.dat | uniq> nouveaufichier.dat
$ find ~ -name "papier*"
Expliquons. find est une commande très utile qui liste tous les fichier
dans une arborescence (qui commence à partir du répertoire home dans ce
cas). Sa sortie peut-être filtrée selon plusieurs critères comme par exemple
-name.
SEARCH ?
Bien sûr, essayez cela :
$ grep -l 'entropie' *
search entropy [...]*.*.*, mais grep n'est pas récursif.
$ find . -exec grep -l "entropy" {} \; 2> /dev/null
find . sort tous les noms des fichiers à partir du
répertoire courant, -exec grep -l "entropy" lance une commande sur chacun
des fichiers (représentés par {}), \ termine la
commande). Si vous pensez que la syntaxe est horrible... vous avez raison :-)
Vous auriez aussi pu écrire le script suivant :
#!/bin/sh
# rgrep: grep récursif
if [ $# != 3 ]
then
echo "Utilisation : rgrep <paramètres> <motif> <répertoire>"
exit 1
fi
find $3 -name "*" -exec grep $1 $2 {} \; 2> /dev/null
grep marche comme SEARCH et combiné avec
find nous obtenons le meilleur des deux mondes.
$ awk 'NL> 2 {print $2, "\t", $5}' fichier.dat> nouveaufichier.dat
awk est en fait un langage de programmation. Pour chaque ligne à partir de
la troisième, on affiche le second et le cinquième champ en les séparant par
une tabulation. Apprenez à vous servir de awk --- il vous fera gagner beaucoup
de temps.
ls-lR.gz d'un FTP. Pour chaque sous
répertoire, il y a une ligne « total x », avec x la
taille en Kilo-octets du répertoire. J'aimerais avoir le total de toutes ces
valeurs.
zcat ls-lR.gz | awk ' $1 == "total" { i += $2 } END {print i}'
zcat sort le contenu du fichier .gz. La sortie est envoyée
vers awk dont je vous recommande chaudement de lire la page man.
monprog, pour
calculer un paramètre à partir d'un fichier de données. Je voudrais le lancer
sur des centaines de fichiers et avoir la liste des résultats, mais c'est une
calamité de demander chaque fois le nom du fichier. Sous VMS, j'aurais écrit un
long fichier de commande. Et sous Linux ?
Un script très court. Faites votre programme pour qu'il cherche
le programme mesdonnées.dat et pour qu'il afficher le résultat sur l'écran
(stdout) et écrivez ensuite ce petit script :
#!/bin/sh
# monprog.sh: lance la même commande sur plusieurs fichiers
# usage: monprog.sh *.dat
for fichier in $* # pour tous les paramètres (e.g. *.dat)
do
# ajouter le nom du fichier dans résultat.dat
echo -n "${fichier}: ">> résultats.dat
# copie le paramètre courant dans mesdonnées.dat et lance monprog
# et ajoute le sortie à résultats.dat
cp ${fichier} mesdonnées.dat ; monprog>> résultats.dat
done
#!/bin/sh
# remplace $1 par $2 dans $*
# utilisation : remplace "vieux-motif" "nouveau-motif" fichier [fichier...]
VIEUX=$1 # premier paramètre
NOUVEAU=$2 # second
shift ; shift # enlever les deux premier paramètres ; les suivants sont
# les noms des fichiers
for fichier in $* # pour tous les fichier donnés en paramètres
do
# remplace toutes les occurrences de VIEUX par NOUVEAU et sauve cela
# dans un fichier temporaire
sed "s/$VIEUX/$NOUVEAU/g" ${fichier}> ${fichier}.nouveau
# renommer le fichier temporaire
/bin/mv ${fichier}.new ${fichier}
done
#!/bin/sh
# prune.sh: efface les n-1ème et n-2ème ligne de fichiers
# utilisation : prune.sh fichier [fichier...]
for fichier in $* # pour chaque paramètre
do
LIGNES=`wc -l $fichier | awk '{print $1}'` # nombre de ligne dans fichier
LIGNES=`expr $LIGNES - 3` # LIGNES = LIGNES - 3
head -n $LIGNES $fichier> $fichier.new # sort les premières lignes
# de LIGNES
tail -n 1 $fichier>> $fichier.new # ajoute la dernière ligne
done
ed :
#!/bin/sh # prune.sh: efface les n-1ème et n-2ème ligne de fichiers # utilisation : prune.sh fichier [fichier...] for fichier in $* # pour chaque paramètre do printf '$-2,$-1d\nw\nq\n' | ed -s $fichier done
J'espère que ces exemples vous auront ouvert l'appétit.