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.