Les commandes Unix/Linux

Didier SIMON

Copyright © Didier SIMON 2007

TABLE DES MATIERES

1  Rechercher des fichiers avec find
    1.1  Recherche simple
    1.2  Les méta-caractères
    1.3  La négation
    1.4  Majuscules/Minuscules
    1.5  Autres critères de recherche
           1.5.1  Recherche par le type
           1.5.2  Recherche par le propriétaire ou le groupe
           1.5.3  Le temps
    1.6  Recherche multi-critères
    1.7  Profondeur de la recherche
    1.8  Affichage des résultats
           1.8.1  L'affichage simple
           1.8.2  L'affichage détaillé
           1.8.3  L'affichage formaté
    1.9  Que faire de tous ces résultats

INTRODUCTION

Si les interfaces graphiques présentent un confort indéniable, il existe beaucoup de situations où la ligne de commande se montre bien plus efficace et il y a même des choses que l'on ne pourrait imaginer faire avec des clics de souris.

Avec ce tutoriel (d'autres suivront), j'espère vous démontrer cela en vous donnant des exemples concrets en commençant par les besoins les plus élémentaires pour aller jusqu'à des cas beaucoup plus complexes.

Dans les tutoriels, nous faisons référence aussi bien aux Unices qu'à Linux et autres systèmes de type Unix tels que FreeBSD, NetBSD et OpenBSD.

1 Rechercher des fichiers avec find

La commande find permet de chercher des fichiers ou des répertoires dans une arborescence de répertoires. C'est une commande particulièrement puissante permettant non seulement d'effectuer des recherches de façon extrèmement précise, mais également de lancer des traitements sur les fichiers ou répertoires trouvés.

1.1 Recherche simple

Ce premier exemple très simple vous montre comment rechercher un fichier du nom de photo.jpg :
find -name photo.jpg
./images/photo.jpg
./images/vacances/photo.jpg

Le résultat nous montre que la recherche à été faite à partir du répertoire courant. C'est le comportement par défaut de find, mais il est possible de préciser un chemin relatif ou absolu, à partir duquel doit s'effectuer cette recherche :

find / -name photo.jpg 

(La recherche se fera à partir de la racine.)

1.2 Les méta-caractères

Nous pouvons utiliser des méta-caractères dans le motif pour remplacer un ou plusieurs caractères lorsque l'on ne connait pas le nom complet. les méta-caractères peuvent être ? pour remplacer 1 caractère, ou * pour remplacer 0 à n caractères. Modifions notre commande comme ceci :

find . -name "photo?.jpg"
./images/photo1.jpg
./images/photo2.jpg
./images/vacances/photoA.jpg
./images/vacances/photoB.jpg

Chaque caractère ? remplace exactement un caractère et nous n'avons donc plus parmis les résultats, les fichiers photo.jpg. puisqu'ils ne comportent aucun caractère entre photo et le point.

Attention ! Remarquez dans la commande, les guillemets qui entourent le motif. Ils sont là pour être sûr que le motif soit bien transmis tel quel à la commande find car nous voulons que ce soit elle qui l'interprète et non le shell qui utilise également les méta-caractères. Une autre méthode consiste à faire précéder chaque méta-caractère par un antislash.

find . -name photo\?.jpg

Si nous n'avions pas utilisé de guillemets ni d'antislash, le shell aurait intercepté le méta-caractère et aurait cherché à établir la correspondance avec d'éventuels fichiers ou répertoires se trouvant dans le répertoire courant avant d'exécuter la commande. S'il s'y trouvait par exemple un fichier du nom de photoA.jpg, alors le shell remplacerait sans nous en informer, le motif par le nom du fichier trouvé et la commande réellement exécutée deviendrait :

find . -name photoA.jpg

Ce n'est bien sûr pas ce que nous voulons.

Si le shell trouve plus d'un fichier correspondant à ce motif, il remplacera le motif par tous les noms de fichiers qu'il a trouvés et la commande ressemblerait alors à ça :

find . -name photoA.jpg photoB.jpg photoC.jpg

La syntaxe de cette dernière commande est incorrecte et son exécution nous renverrait alors un message d'erreur. Il est cependant possible d'utiliser plusieurs motifs ou critères de recherche, et nous verrons plus loin comment faire.

L'oubli des guillemets est une erreur assez sournoise car comme nous l'avons vu, selon le cas, nous n'obtenons pas toujours de message d'erreur. De plus, si le shell ne trouve aucun fichier correspondant, le méta-caractère ne sera pas interprêté par lui et la commande s'exécutera comme nous l'avions prévu. On peut donc répéter l'erreur de nombreuses fois sans même s'en rendre compte.

S'il faut remplacer un nombre indéterminé de caractères, alors nous utiliserons le caractère * comme dans ce nouvel exemple :

find . -name "photo*.jpg"
./images/photo.jpg
./images/photo1.jpg
./images/photo2.jpg
./images/photo75.jpg
./images/vacances/photo.jpg
./images/vacances/photoA.jpg
./images/vacances/photoB.jpg
./images/vacances/photoAnniversaire.jpg

1.3 La négation

Il peut arriver que nous voulions exclure certains fichiers du résultat d'une recherche. find utilise pour cela le caractère ! (point d'exclamation) en signe de négation que l'on place devant l'expression à inverser. Dans notre prochain exemple, en faisant précéder -name du caractère de négation, nous obtiendrons tous les fichiers et répertoires ne contenant pas dans leur nom la chaîne "photo" :

find . ! -name "*photo*"

1.4 Majuscules/Minuscules

Par défaut, find est sensible à la casse, c'est à dire qu'il différencie les majuscules et les minuscules. Une recherche de "photo.jpg" ne permettra pas de trouver le fichier "Photo.jpg". Pour rendre find insensible à la casse, il faut utiliser le paramètre -iname à la place de -name.

find . -iname "photo.jpg"

trouvera aussi bien Photo.JPG que photo.jpg.

1.5 Autres critères de recherche

Le nom ne suffit pas toujours à trouver notre bonheur. Nous préfèrerions parfois trouver certains types de fichiers, ceux appartenant à un utilisateur ou encore ceux qui ont été modifiés depuis un certain temps. find vous offre une multitude de paramètres afin de réaliser toutes sortes de recherches.

1.5.1 Recherche par le type

Recherche de fichiers :

find -type f

Recherche de répertoires :

find -type d

Recherche de liens symboliques :

find -type l

1.5.2 Recherche par le propriétaire ou le groupe

find -user michel
find -group compta

1.5.3 Le temps

Il est quelques fois intéressant de savoir quels fichiers ont été modifiés ou auxquels on a accédé depuis un certain laps de temps. Il est également important et particulièrement pour un l'administrateur d'un système, de vérifier si les droits d'accès de fichiers ou de répertoires ont été changés. Il existe plusieurs paramètres pour cela, composés d'un préfixe qui détermine le type d'information que l'on veut vérifier, et d'un sufixe qui précise l'interval de temps.

Les préfixes sont a pour accès, m pour modification et c pour status et les suffixes sont time pour une tranche de 24 heures et min pour les minutes. La valeur numérique donnée peut être précédée des signes + ou - s'il faut prendre en compte l'interval se situant avant ou après l'information de temps.

les fichiers ayant été mofifiés il y a moins de 30 minutes :

find -type f -and -mmin -30

Les répertoires auxquels on n'a pas accédé depuis plus de 72 heures :

find -type d -and -atime +3

Les entrées du répertoire /etc et de ses sous répertoires qui ont vu leurs droits d'accès modifiés ces dernières 24 heures :

find /etc -ctime -1

La valeur donnée aux paramètres xtime indique un nombre de jours, mais il s'agit de n jours à la même heure. Or nous voulons généralement avoir des informations sur les n dernières journées complètes. find autorise cela grace au paramètre -daystart. En modifiant ainsi notre dernier exemple, nous obtenons les mêmes informations mais sur toute la journée d'hier.

find /etc -daystart -ctime -1

Il est possible d'omettre le signe, et le temps est alors donné pour exact mais cela n'a généralement pas beaucoup d'utilité.

1.6 Recherche multi-critères

Nous avons évoqué plus haut la possibilité de faire des recherches multi-critères. Nous pouvons en effet combiner les effets des différents critères disponibles en les associant à l'aide d'opérateurs logiques tels que -and (ET) ou -or (OU). Il est ainsi possible de cumuler plusieurs critères comme le montre l'exemple suivant.

Les fichiers contenant la chaîne photo ou picture, sans différencier les minuscules et les majuscules, répertoires exclus et ayant été modifiés il y a moins de 30 minutes :

find . \( -iname "*photo*" -or -name "*picture*" \) -and ! -type d -and -mmin -30

Les parenthèses sont nécessaires lorsque l'on veut rendre une expression prioritaire. Pour la même raison que pour les métacaractères, nous devons empêcher que ces dernières soient interprétée par le shell et pour cela nous utilisons ici le caractère \ (backslash). Il existe un ordre de priorité des opérateurs qui peut nous éviter d'avoir recours aux parenthèses. par exemple, l'opérateur -or est prioritaire par rapport à -and ce qui fait que dans notre exemple, les parenthèses n'étaient pas indispensables. Toutes fois, il est intéressant de les utiliser malgré tout pour des raisons de lisibilité et pour éviter des erreurs lorsque la combinaison des expressions devient relativement complexe.

1.7 Profondeur de la recherche

Nous l'avons vu, find effectue ses recherches de façon récursive. Quelques fois, il est inutile d'aller très loin dans l'arborescence. Nous avons alors la possibilité de préciser le niveau de récursivité de la recherche que nous voulons effectuer grâce au paramètre -maxdepth. Une valeur de 1 permet de s'arrêter au seul répertoire indiqué comme point de départ ou bien uniquement le répertoire courant par défaut. Cela nous permettrait par exemple d'obtenir la liste des répertoires d'utilisateurs ayant ou ayant eu un compte sur ce poste.

find /home -maxdepth 1 -type d

A l'inverse, le paramètre -mindepth nous permet de ne faire des recherches que dans les sous-répertoires les plus profonds. Si vous connaissez une application utile à ce paramètre, je vous invite à m'en faire part.

1.8 Affichage des résultats

Vous avez pu entrevoir la précision avec laquelle nous pouvons indiquer à find ce que nous recherchons. Vous allez voir que nous pouvons avec la même précision affecter la manière dont il doit afficher les résultats de ces recherches. Dans les exemples que vous avez pu voir jusqu'ici, chaque fichier ou répertoire trouvé était affiché avec son chemin relatif au répertoire de départ. C'est ainsi que find présente le résultat de ses recherches en l'absence d'indications.

1.8.1 L'affichage simple

Le premier des paramètres dédiés à l'affichage est -print. il ne prend aucun argument et c'est le paramètre par défaut. Son utilisation seule donnera le même résultat que si nous l'omêtons, mais Nous verrons plus loin qu'il est parfois nécessaire de l'utiliser.

1.8.2 L'affichage détaillé

Une deuxième manière d'afficher le résultat est l'affichage détaillé à la façon ls -l avec le paramètre -ls. Nous ne nous étendrons pas sur ce paramètre.

1.8.3 L'affichage formaté

Un paramètre particulièrement intéressant est le paramètre -printf. Les programmeurs C l'auront deviné, il permet d'effectuer une sortie formatée du résultat grace à une chaîne de formatage (Attention cependant, car si la syntaxe est assez proche, les caractères indiquant les éléments à afficher sont quant à eux différents). Grace à ce paramètre, il est possible d'afficher n'importe quelles informations concernant les fichier ou les répertoires. Par exemple, la date et l'heure de leur dernier accès :

find . -printf "%h/%f : dernier accès le %AA %Ad %AB %AY à %AH:%AM:%AS\n"
...
./GNUstep/Defaults/WindowMaker : dernier accès le mercredi 28 juin 2004 à 19:50:20
./GNUstep/Defaults/WMRootMenu : dernier accès le mercredi 28 juin 2004 à 19:50:20
./GNUstep/Defaults/WMState : dernier accès le mercredi 28 juin 2004 à 19:50:20
./GNUstep/Defaults/WMState~ : dernier accès le mercredi 28 juin 2004 à 19:50:20
./GNUstep/Defaults/WMWindowAttributes : dernier accès le mercredi 28 juin 2004 à 19:50:20
...

Observons la ligne de commande et le résultat ci-dessus. La chaîne entre guillemets est la chaîne de format. On y voit du texte, qui sera affiché tel quel, des variables (commençant par le caractère \%) et un caractère spécial \n (le backslash étant le caractère d'échappement pour insérer les caractères spéciaux).

La variable \%h représente le chemin d'accès au fichier et \%f le nom du fichier. (il ne faut pas oublier le / entre \%h et \%f car ni l'un ni l'autre ne l'affichent). \%A introduit un élément de la date du dernier accès au fichier. Elément défini par le caractère qui lui est accollé : A pour le jour de la semaine en toutes lettres, (un a minuscule aurait inséré le jour en version abrégée), d pour le quantième du mois, B pour le nom du mois, (de même que pour le a, un b minuscule aurait inséré la version abrégée du mois), Y pour l'année sur 4 chiffres ... je vous laisse deviner pour H, M et S. Et enfin le \n bien connu des programmeurs C et qui crée un retour à la ligne.

Pour illustrer les possibilités de find, nous avons choisi d'insérer nous même chaque détail composant la date dans la chaîne de format, mais pour ce cas précis, nous aurions pu obtenir un résultat similaire en utilisant moins de variables puisque la variable \%Ac donne à elle seule la date (en abrégé) et l'heure.

find . -printf "%h/%f : dernier accès le %Ac\n"
...
./GNUstep/Defaults/WindowMaker : dernier accès le mer 28 jun 2004 19:50:20 CEST
./GNUstep/Defaults/WMRootMenu : dernier accès le mer 28 jun 2004 19:50:20 CEST
...

De la même manière que \%A* permet d'afficher la date de dernier accès, il est possible de faire référence à la date de la dernière modification grâce aux variables \%T*, ou encore à la date de dernière modification du status du fichier avec les variables \%C*.

Les nombreuses variables donnent d'ailleurs beaucoup d'autres possibilité comme par exemple, afficher le nom du propriétaire du fichier (\%u), ou la taille de ce même fichier en nombre de blocs de 512 octets (\%b), etc. Je vous invite à consulter la page de manuel de find pour connaître l'ensemble des variables utilisables avec le paramètre -printf.

1.9 Que faire de tous ces résultats

Bien que la liste ne soit pas exhaustive, vous pouvez constater la précision avec laquelle find permet de trouver et afficher les informations. Mais cela ne s'arrête pas là ! Si nous avons déployé tous ces efforts pour trouver nos fichiers et/ou nos répertoires, c'est pour en faire quelque chose. (les copier, les déplacer, les supprimer, changer leurs droits d'accès, etc). En plus de nous aider admirablement dans la recherche de nos précieux fichiers, find nous permet d'enchaîner notre recherche avec une action permettant d'exploiter les éléments trouvés.

Le paramètre -exec nous permet cet enchaînement en exécutant n'importe quelle commande du shell sur les fichiers issus de la recherche. Supposons par exemple que nous souhaitions supprimer tous les fichiers objets (*.o) d'un projet. Nous n'aurions qu'à taper cette commande :

find projet/src/ -name "*.o" -exec rm -f {} \;

Nous utilisons ici la commande rm avec son paramètre -f pour ne pas avoir de confirmation à donner. les accolades représentent l'occurence de chaque fichier trouvé et l'antislash et le point virgule sont là pour cloturer la commande.