Les HOWTO Linux...
Page suivante - Page précédente - Table des matières
11. Exemples du monde réel
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
- J'ai un fichier qui contient une liste de mots. Je veux les
trier dans l'ordre inverse et les imprimer.
$ cat fichier.txt | sort -r | lpr
- Mon fichier de données contient des doublons. Comment les
effacer ?
$ sort fichier.dat | uniq> nouveaufichier.dat
- J'ai un fichier appelé papier.txt ou papier.tex ou quelques choses dans
le genre mais je ne m'en rappelle plus. Comment le retrouver ?
Expliquons.$ find ~ -name "papier*"
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
. - J'ai un fichier texte qui contient le mot « entropie » dans
ce répertoire. Existe-t-il quelque chose de comparable à
SEARCH
? Bien sûr, essayez cela :$ grep -l 'entropie' *
- Quelque part, j'ai un fichier texte qui contient le mot
« entropy » et j'aimerai le retrouver. Sous VMS j'aurais utilisé
search entropy [...]*.*.*
, maisgrep
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
Voici l'explication.grep
marche commeSEARCH
et combiné avecfind
nous obtenons le meilleur des deux mondes. - J'ai un fichier qui a deux lignes d'en-tête et qui a ensuite n
données par ligne, pas nécessairement espacées de la même manière. Je veux
extraire la deuxième et le cinquième champs de chaque ligne. Dois-je écrire un
programme en Fortran ?
Nan. Ceci est plus rapide :
$ 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. - J'ai téléchargé le
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. - J'ai écrit un programme en Fortran,
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
- Je veux remplacer « géologie » par
« géophysique » dans tous mes fichiers textes. Dois-je les éditer
manuellement ?
Nan. Écrivez ce script :
#!/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
- J'ai des fichier contenant des données. Je ne connais pas leur
taille et je dois enlever leur avant-dernière et leur avant-avant-dernière
lignes. Heu... à la mimine ?
Bien sûr que non :
#!/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
NDT : il est tout de même beaucoup plus élégant d'utilisered
:#!/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.
Page suivante - Page précédente - Table des matières