Exercice sur les filtres et redirections Unix find, grep, ls, sort,

 

1.  Créez un fichier dont chaque ligne commence par un chiffre, suivi d'un slash (/), puis d'un ou plusieurs mots.
     1. Affichez les lignes de ce fichier triées en ordre croissant, suivant le nombre placé en début de ligne;
     2. Éliminez de chaque ligne le chiffre et le caractère «/»;
     3. Triez ces lignes par ordre alphabétique inverse.
2.  Combien de fichiers de configuration avez-vous ?
3.  Combien de répertoires de configuration avez-vous ?
4.  Comment mettre dans un fichier la liste de tous les fichiers de l'arborescence à partir du répertoire courant? 
5.  Créez un fichier liste contenant la liste de tous vos fichiers, avec leur taille, leurs droits, etc.
6.  Comment afficher uniquement les fichiers du répertoire courant qui sont des liens symboliques ?
7.  Combien de lignes contiennent le mot «file» dans la page de man de syst ?
8.  Quels sont les dix plus gros fichiers de /usr/bin/ ?
9.  Pour chaque ligne du fichier /etc/hosts, affichez :
     * Le cinquième caractère; 
     * Les caractères 5 à 10, et le treizième;
     * Tous les caractères à partir du quinzième.


 

  1. Créez un fichier dont chaque ligne commence par un chiffre, suivi d'un slash (/), puis d'un ou plusieurs mots.

    C'est la commande sort qui permet de trier des fichiers selon un ordre donné.

    1. Affichez les lignes de ce fichier triées en ordre croissant, suivant le nombre placé en début de ligne

      sort sans option trie automatiquement en fonction du premier caractère, par ordre alphabétique si c'est une lettre, par ordre croissant si ce sont des chiffres. Il suffit donc de taper :

      sort fichier
    2. Éliminez de chaque ligne le chiffre et le caractère «/».

      Pour cela, sans utiliser d'éditeur, on peut utiliser la commande cut, qui élimine des champs dans une ligne. Par défaut, le séparateur de champs est une tabulation. Ici, on peut demander à cut de considérer le slash comme un séparateur de champs (option -d, «délimiteur»), et de ne conserver que le deuxième champ du fichier (option -f, field). On redirige ensuite la sortie dans un autre fichier :

       cut -d/ -f2 fichier > fichier2
    3. Triez ces lignes par ordre alphabétique inverse. C'est l'option -r (reverse) de sort qui inverse le résultat de la comparaison. Par défaut, sort trie par ordre alphabétique, il suffit donc de taper :
      sort -r fichier2
  2. Combien de fichiers de configuration avez-vous ?

    La réponse n'est pas simple, car vous avez également des répertoires de configuration, comme .netscape/ qui contient entre autres vos marque-pages (bookmarks.html), vos préférences (preferences), etc. On va compter le nombre de fichiers commençant par un point situés dans votre répertoire principal, en éliminant les copies de sauvegarde (qui finissent par un tilde). Il y a plusieurs manières de procéder.

    1. ls, grep, tr, cut

      On peut penser à une solution complexe et bien lourde utilisant toutes ces commandes, ce qui permet de les apprendre plus qu'autre chose... On affiche une liste longue avec l'ensemble des fichiers (ls -la) puis qui élimine tous les répertoires et les liens avec grep en ne gardant que les lignes qui commencent par un tiret :

      ls -al | grep '^-'

      Ensuite, on utilise tr pour ne conserver qu'un seul espace entre chaque champ de la liste, en utilisant l'option -s (squeeze) qui remplace par une seule occurence la répétition d'un caractère spécifié; on met des apostrophes autour de l'espace pour qu'il soit compris comme tel et non comme un simple espace :

      tr -s ' ' 

      On utilise cut pour conserver le dernier champ avec les noms de fichiers (en l'occurence le neuvième champ), en indiquant que l'espace sert de délimiteur de champ :

       cut -d' ' -f9 

      Enfin, on demande à grep de ne retenir que les fichiers commençant par un point, et ne finissant pas par un tilde, et on les comptel'option -c de grep. Cela donne pour finir :

       ls -al | grep '^-' | tr -s ' ' | cut -d' ' -f 9 | grep -c '^\..*[^~]$'
      

      Mais que de tourments pour si peu... :-)

    2. ls et grep

      Il y a plus simple... On demande à ls une liste des fichiers commençant par un point (avec l'option -d pour ne pas descendre dans les répertoires de configuration), on ne garde que les lignes ne finissant pas par un / ou un tilde, et on compte :

      ls -ad .* | grep -vc '\(~\|/\)$' 
    3. find

      On demande à find de chercher dans le répertoire courant (.), sans descendre dans l'arborescence (-maxdepth 1), tous les fichiers normaux (-type f : file), dont le nom commence par un point (-name '.*'). On les compte ensuite avec wc :

      find . -maxdepth 1 -name '.*' -type f | wc -l

      Cette solution est préférable car elle ne lance que deux processus et non pas au moins cinq comme la précédente.

  3. Combien de répertoires de configuration avez-vous ?

    Il y a deux solutions, l'une faisant appel à ls et grep, l'autre faisant appel à find.

    1. ls et grep

      Le principe est le même que dans l'exercice précédent. La différence est que grep va chercher les lignes qui commencent par un point et finissent par un slash. Cela se fait de la manière suivante :

      grep '^\..*/$'

      .* signifie «n'importe quel caractère (point) répété zéro ou plusieurs fois (étoile)».

      On tape donc :

      ls -ad .* | grep '^\..*/$' | wc -l

      On part ici du principe que vous avez un alias de ls sur ls -F (qui met un slash après les noms de répertoires, une étoile après les noms d'exécutables et une arobase après les noms de liens). Si ce n'est pas le cas, ajoutez-le dans un fichier .alias ou tapez ls -lF.

    2. find

      On demande à find de chercher tous les fichiers de type «répertoire» (-type d : directory), et dont le nom commence par un point (-name '.*', les quotes servant à protéger du shell le contenu de l'expression), dans descendre dans l'arborescence.

      On tape donc :

      find . -maxdepth 1 type d -name '.*'  | wc -l

    Il y a une inexactitude dans le résultat : find compte aussi ./ dans le résultat.

  4. Comment mettre dans un fichier la liste de tous les fichiers de l'arborescence à partir du répertoire courant ?

    C'est l'option -R de ls qui permet d'afficher récursivement le contenu d'un répertoire et de ses sous-répertoires (à ne pas confondre avec -r qui inverse le tri). Pour rediriger la sortie d'une commande dans un fichier, on utilise le caractère >. Pour mettre la liste de tous les fichiers de l'arborescence dans un fichier toto, il faut donc taper :

     ls -R > toto 
  5. Créez un fichier liste contenant la liste de tous vos fichiers, avec leur taille, leurs droits, etc

    Il va s'agir de faire une liste récursive de l'ensemble de votre compte (option -R de ls), incluant les fichiers de configuration (option -a) et les renseignements donnés par l'option -l.

    De la longue liste obtenue, on ne veut retenir que les fichiers, dont les droits commencent par un tiret (un d identifie les répertoires). On va donc demander à grep de chercher toutes les lignes commençant par un tiret.

    Enfin, on va placer le résultat dans un fichier appelé liste. On tape donc :

    ls -alR | grep '^-' > liste
  6. Comment afficher uniquement les fichiers du répertoire courant qui sont des liens symboliques ?

    L'option -l de ls donne une liste longue des fichiers, incluant les droits et le type des fichiers, identifiés par une lettre : rien pour un fichier, «d» pour un répertoire (directory), «l» pour un lien (link); par exemple :

    drwxr-xr-x   2 emilia   users        1024 mai 10 02:27 www/
    

    Pour obtenir la liste des fichiers du répertoire courant qui sont des liens symboliques, il suffit donc d'afficher cette liste longue et de ne retenir que les lignes qui commencent par un «l», grâce à la commande grep. On utilise une expression régulière pour cela : le chapeau (^) désigne le début de la ligne, et l'ensemble de l'expression est placée entre apostrophes pour qu'elle ne soit pas interprétée par le shell. On tape donc :

    ls -l | grep '^l' 
  7. Combien de lignes contiennent le mot «file» dans la page de man de less ?

    Il faut lancer le man de less, et ensuite chercher dedans le nombre de lignes contenant le mot file («fichier» en anglais), avec grep. C'est l'option -c (count) de grep qui va servir.

    Finalement, on écrit :

    man less | grep -c  file

    Et on obtient 205. C'est le nombre de lignes contenant au moins une fois la chaîne de caractères file, mais pas le nombre d'occurences du mot dans le fichier : il pourrait y avoir plusieurs fois file sur la même ligne. On atteint là encore la limite de ce que sait faire grep.

  8. Quels sont les dix plus gros fichiers de /usr/bin/ ?

    Il faut d'abord faire une liste des fichiers avec leurs tailles (option -l de ls. Ensuite, il faut trier ces lignes en fonction de la taille, avec la commande sort. Une ligne est de la forme suivante :

    -rwxr-xr-x   1 root     staff        5872 Jan 21  1994 /usr/bin/rm*
    

    C'est le cinquième champ, celui de la taille, qui nous intéresse. La numérotation commençant à 0 (comme les étages), pour indiquer le cinquième champ on écrit +4. Ensuite, on veut que le tri se fasse selon un critère numérique (option -n) et à l'envers, en commençant par les plus grandes valeurs (option -r, reverse).

    Pour finir, on veut les dix premières lignes du résultat. On les sélectionne avec la commande head; par défaut, elle prend les dix premières lignes d'un fichier, il n'est donc pas nécessaire de préciser le nombre de lignes voulues. Finalement, on écrit :

    ls -l /usr/bin | sort -nr +4 | head
  9. Pour chaque ligne du fichier /etc/hosts, affichez :
    • Le cinquième caractère;
    • Les caractères 5 à 10, et le treizième;
    • Tous les caractères à partir du quinzième.

    Une manière de résoudre cet exercice consiste à utiliser le programme sed qui sert à manipuler du texte.

    Nous allons utiliser la commande s de sed. Sa syntaxe est la

    s/regexp/remplacement/

    regexp est une expression régulière et remplacement une chaîne devant la remplacer.

    • Pour afficher le cinquième caractère de chaque ligne, on peut faire ceci :
      clipper ~ $ cat /etc/hosts | sed -e "s/^.\{4\}\(.\).*/\1/"
      

      Le "^.\{4\}" du début sert à filtrer les 4 premiers caractères de chaque ligne. Ensuite, \(.\) filtre n'importe quel caractère, le fait de mettre des parenthèses enregistre le caractère en question dans une variable que l'on peut utiliser dans la chaîne de remplacement avec "\1". Ensuite, .* filtre le reste de la ligne.

    • Sur le même principe, pour afficher les caractères 5 à 10 et le treizième :
      clipper ~ $ cat /etc/hosts | sed -e "s/^.\{4\}\(.\{6\}\)..\(.\).*/\1 \2/"
      
    • Et enfin, pour afficher tous les caractères à partir du quinzième :
      clipper ~ $ cat /etc/hosts | sed -e "s/^.\{14\}//"