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 ?
    $ 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.
  • 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 [...]*.*.*, 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
    

    Voici l'explication. grep marche comme SEARCH et combiné avec find 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'utiliser 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.


Page suivante - Page précédente - Table des matières