Blog de Norore
Geek en perdition dans un monde qui va trop vite

Chercher des fichiers entre deux dates

01 May 2019 - Norore
Des lunettes posées sur une page d'un livre avec du texte surligné.

Est-ce que ça ne vous est jamais arrivé, de chercher un fichier et de ne pas le trouver ? Ou pire, de trouver beaucoup trop de fichiers alors que vous savez, à peu près, à quand remonte la dernière fois où vous avez modifié celui que vous cherchiez ? Si vous êtes utilisateur de Linux, la commande find est faite pour vous ! Jouons un peu ensemble avec, et c’est aussi l’occasion de faire un nouveau billet technique ici, juste, parce que !

Présentation de find

Avant de nous lancer dans la création d’un script, une petite présentation de la commande find s’impose.

Il s’agit d’une commande de base sous tout bon système d’exploitation GNU/Linux qui se respecte, et probablement aussi ailleurs, ne connaissant pas —peu— les autres systèmes, abstenons-nous de nous avancer. Si vous êtes sous Debian, Arch ou encore Ubuntu, c’est super, vous avez tout ce qu’il vous faut !

Voici un extrait de la traduction française du début du manuel :

find parcourt les arborescences de répertoires commençant en chacun des chemins mentionnés, en évaluant les expressions fournies pour chaque fichier rencontré. L’évaluation de l’expression se fait de gauche à droite, en suivant des règles de priorité décrites dans la section OPÉRATEURS, jusqu’à ce que le résultat soit connu (par exemple la partie gauche vraie pour un opérateur OU ou fausse pour un opérateur ET).

Vous pouvez lire la page complète sur le site de Damien Pobel : http://pwet.fr/man/linux/commandes/find/

La commande find est très souvent utilisée pour rechercher des fichiers dans le système d’exploitation. Si vous l’utilisez de façon basique, elle peut vous remonter beaucoup d’informations, et parfois même vous dire qu’elle n’a pas pu lire certains fichiers parce que l’utilisateur actuel —vous— n’a pas les droits d’accès, typiquement pour lire les fichiers dans la racine / ou dans le répertoire d’un autre utilisateur, ce qui peut arriver si vous utilisez un ordinateur partagé.

Par exemple, si je cherche tous les fichiers dont l’extension est sh dans mon home, voici la commande que je devrais saisir :

find ~ -name "*.sh"

Ici, find cherche dans le répertoire home ~ (oui, c’est une tilde) tous les répertoires et fichiers dont le nom fini par .sh et qui est précédé par aucun ou une infinité de caractères, défini par le caractère *. Notez bien que le nom est protégé entre deux apostrophes, c’est une subtilité du shell, pour éviter que la commande s’arrête aux fichiers dont l’extension est sh et qui sont dans le répertoire lu. Vous pouvez tester vous-même pour comprendre la différence, avec et sans apostrophes.

Voici ce que la commande m’a retourné comme résultat (quelques résultats) :

/home/norore/bibisco/WebContent/js/bootstrap/select2-3.4.3/release.sh
/home/norore/.vim/bundle/vim-markdown/test/run-tests.sh
/home/norore/Minecraft/Mineternity_projet/clean_mc_log.sh
/home/norore/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/sass-3.7.3/extra/sass-spec-ref.sh
/home/norore/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/sassc-2.0.0/ext/libsass/version.sh
/home/norore/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/mini_portile2-2.3.0/concourse/tasks/rake-test/task.sh
/home/norore/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/sass-3.4.25/extra/sass-spec-ref.sh
/home/norore/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/safe_yaml-1.0.4/bundle_install_all_ruby_versions.sh
/home/norore/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/safe_yaml-1.0.4/run_specs_all_ruby_versions.sh
/home/norore/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/sass-3.6.0/extra/sass-spec-ref.sh
/home/norore/Programmation/CV/vendor/bundle/ruby/2.3.0/gems/kramdown-1.16.2/benchmark/benchmark.sh
/home/norore/foo.sh
/home/norore/TeamSpeak/ts3client_runscript.sh
/home/norore/Scripts/purge_texfiles.sh
/home/norore/tor-browser_en-US/Browser/run-mozilla.sh
/home/norore/tor-browser_en-US/Browser/updated/run-mozilla.sh
/home/norore/softwares/gajim/win/dev_env.sh
/home/norore/softwares/gajim/win/build.sh
/home/norore/softwares/gajim/win/_base.sh
/home/norore/Téléchargements/imagescan-bundle-linuxmint-18-1.3.28.x64.deb/install.sh

Bon, ça vous donne beaucoup de fichiers, un peu trop même, soit. Comment faire alors ? Éh bien sachez que find est une commande puissante, très puissante, un peu trop même pour un simple billet de blog. Mais voyons tout de même quelques exemples d’utilisation ensemble pour apprendre à l’utiliser.

Trois cas d’utilisations classiques

Chercher des répertoires

Maintenant que nous avons vu comment trouver des fichiers spécifiquement, attaquons-nous à une autre partie qui peut être tout aussi utile et pratique : la recherche de répertoires ! Pourquoi est-ce que je dis qu’elle est pratique ? Tout simplement parce que, comme les exemples précédents l’ont illustrés, le nombre de fichiers trouvés, et donc de lignes à afficher, peut être conséquent. Or il peut arriver que l’on connaisse le nom d’un répertoire où devrait se situer le fichier, mais plus son chemin exact. Et bien c’est là que l’option -type, déjà présentée, peut être très utile ! Plutôt que de préciser l’argument f, pour file (fichier), nous allons passer l’argument d, pour directory (répertoire).

Voici un petit exemple sur les répertoires intitulés scripts :

find . -type d -name "scripts"

Ce qui nous donne le résultat suivant :

./.local/share/nautilus/scripts
./.vim/bundle/YouCompleteMe/third_party/ycmd/cpp/ycm/tests/gmock/gtest/scripts
./.vim/bundle/YouCompleteMe/third_party/ycmd/cpp/ycm/tests/gmock/gtest/xcode/Scripts
./.vim/bundle/YouCompleteMe/third_party/ycmd/cpp/ycm/tests/gmock/scripts
./.vim/bundle/YouCompleteMe/third_party/ycmd/third_party/JediHTTP/vendor/jedi/scripts
./.vim/bundle/YouCompleteMe/third_party/ycmd/third_party/JediHTTP/vendor/parso/scripts
./.vim/bundle/YouCompleteMe/third_party/ycmd/third_party/racerd/scripts
./Projets/ScolariteGestionEleves/Scripts
./Projets/ScolariteGestionEleves/Symfony/Scolarite/vendor/symfony/symfony/src/Symfony/Component/Intl/Resources/data/scripts
./Projets/Scripts
./Projets/Tests/Symfony/ldap-auth/vendor/symfony/symfony/src/Symfony/Component/Intl/Resources/data/scripts
./.mysql/workbench/scripts
./.gimp-2.8/scripts

C’est super ! Mais j’ai oublié un détail ! Imaginons que vous ne trouvez pas le bon répertoire, parce que vous avez oublié qu’il a une casse spécifique, et qu’il peut donc avoir une majuscule au début. Et bien pour cela nous allons pouvoir faire une recherche insensible à la casse en remplaçant l’option -name par l’option -iname :

find . -type d -iname "scripts"

Ce qui nous donne le résultat suivant :

./.local/share/nautilus/scripts
./.vim/bundle/YouCompleteMe/third_party/ycmd/cpp/ycm/tests/gmock/gtest/scripts
./.vim/bundle/YouCompleteMe/third_party/ycmd/cpp/ycm/tests/gmock/gtest/xcode/Scripts
./.vim/bundle/YouCompleteMe/third_party/ycmd/cpp/ycm/tests/gmock/scripts
./.vim/bundle/YouCompleteMe/third_party/ycmd/third_party/JediHTTP/vendor/jedi/scripts
./.vim/bundle/YouCompleteMe/third_party/ycmd/third_party/JediHTTP/vendor/parso/scripts
./.vim/bundle/YouCompleteMe/third_party/ycmd/third_party/racerd/scripts
./Projets/ScolariteGestionEleves/Scripts
./Projets/ScolariteGestionEleves/Symfony/Scolarite/vendor/symfony/symfony/src/Symfony/Component/Intl/Resources/data/scripts
./Projets/Scripts
./Projets/Tests/Symfony/ldap-auth/vendor/symfony/symfony/src/Symfony/Component/Intl/Resources/data/scripts
./.mysql/workbench/scripts
./.gimp-2.8/scripts

Chercher des fichiers pour un utilisateur donné

Une des forces de find, surtout si vous travaillez dans un environnement partagé, comme dans le cas des clusters de calcul, c’est que vous pouvez chercher des fichiers en fonction de l’utilisateur qui en est l’heureux propriétaire. Nous allons donc chercher les fichiers appartenant à l’utilisateur root.

Non, je rigole ! Ça va juste vous donner un résultat indigeste ! Et accessoirement, mon terminal vient de planter en lançant la commande, bravo… Nous allons plutôt chercher des fichiers appartenant à l’utilisateur www-data, ça devrait être plus léger !

find /var/www/ -type d -user www-data

Dans cet exemple, je cherche tous les répertoires, grâce à l’option -type d, appartenant à l’utilisateur www-data, grâce à l’option -user suivie du nom de l’utilisateur www-data, à partir du répertoire /var/www/ de mon système de fichiers. Pour les gens ne connaissant pas l’utilisateur www-data, il s’agit d’un utilisateur particulier, très souvent défini dans les systèmes GNU/Linux, qui est utilisé par la plupart des serveurs web, comme Apache ou Nginx. Par convention, les différents fichiers des sites internets sont placés dans le répertoire /var/www/.

Voici le résultat sur la machine de mon serveur personnel (quelques résultats) :

/var/www/norore.fr/
/var/www/norore.fr/FreshRSS
/var/www/norore.fr/FreshRSS/extensions
/var/www/norore.fr/FreshRSS/extensions/Tumblr-GDPR
/var/www/norore.fr/FreshRSS/Docker
/var/www/norore.fr/FreshRSS/data
/var/www/norore.fr/FreshRSS/data/PubSubHubbub
/var/www/norore.fr/FreshRSS/data/PubSubHubbub/keys
/var/www/norore.fr/FreshRSS/data/PubSubHubbub/feeds
/var/www/norore.fr/FreshRSS/data/PubSubHubbub/feeds/aHR0cDovL2ZlZWRzLmZlZWRidXJuZXIuY29tL3N5bWZvbnkvYmxvZw
/var/www/norore.fr/wiki/lib/images/toolbar
/var/www/norore.fr/wiki/lib/images/license
/var/www/norore.fr/wiki/lib/images/license/button
/var/www/norore.fr/wiki/lib/images/license/badge
/var/www/norore.fr/wiki/lib/images/interwiki
/var/www/norore.fr/wiki/conf
/var/www/norore.fr/css

Chercher des fichiers datant de moins d’une semaine

L’un des exemples classiques d’utilisation de la commande find, c’est de chercher la liste des fichiers qui datent de moins de X jours. Nous allons donc voir comment, simplement, nous pouvons trouver des fichiers qui datent de moins d’une semaine, donc, moins de sept jours.

find Programmation/ -type f -ctime -7 -print0 | xargs -0 ls -l

Dans cet exemple, je cherche tous les fichiers, avec l’option -type f datant de moins de 7 jours avec l’option -ctime 7. Pour m’assurer qu’il s’agit bien de fichiers qui ont été modifiés il y a moins de 7 jours, je redirige le flux de sortie de la commande find grâce à un pipe représenté par la barre verticale |, et je demande à la commande xargs d’utiliser les résultats de find pour les donner à la commande ls -l.

Voici le résultat obtenu :

-rw-r--r-- 1 norore norore 238 28 avril 16:45 Programmation/tests/text.xml
-rw-r--r-- 1 norore norore 113 28 avril 13:23 Programmation/tests/text.xml~
-rw-r--r-- 1 norore norore 310 28 avril 16:46 Programmation/tests/text.xsd
-rw-r--r-- 1 norore norore 449 28 avril 15:11 Programmation/tests/text.xsd~

Explorons un peu plus les possibilités de find

Trouver des fichiers entre deux dates

Nous y voilà. Voici enfin une explication de comment faire pour trouver des fichiers entre deux dates. Si vous avez lu jusqu’ici, bravo. Sinon, c’est que vous devez très certainement en connaître plus que moi, ce qui n’est pas dur, et dans ce cas-là je me demande bien ce que vous faites ici ;-) !

find /Documents -newermt 2019/03/26 ! -newermt 2019/03/31 -print0 | xargs -0 ls -l

L’option -newermt permet de chercher tous les fichiers qui ne sont pas plus vieux que la date indiquée. La date doit ête au format année/mois/jour pour être interprêtée correctement. Le fait de préciser ! -newermt permet de préciser l’intervalle, c’est à dire qu’à partir de la seconde date, nous demandons à find de ne pas tenir compte des fichiers. Oui, c’est subtil, mais c’est génial quand on arrive à comprendre comment ça marche !

Ce qui nous donne ce résultat :

-rw-r--r-- 1 norore norore 5292056 30 mars  11:18 'Documents/Guild Wars 2/Screens/gw053.bmp'

Exécuter une commande sur les fichiers

Vous êtes encore là ? Mais c’est merveilleux :-D !

Vous avez trouvé vos fichiers et vous vous apprêtez à rediriger le flux dans une autre commande ? Surtout pas, malheureux ! Utilisez find pour celà ;-) !

Voici un petit exemple simple qui permet de modifier les droits d’accès sur des fichiers OGG uniquement :

find . -iname "*.ogg" -exec chmod 655 {} \;

Dans cet exemple, nous utilisons l’option -exec pour passer une commande, ici, chmod 655, en lui précisant de modifier les droits sur le fichier trouvé par find grâce aux accolades {}. La ligne doit toujours se terminer par \;, sinon vous aurez, soit aucun résultat, soit une erreur.

-rw-r-xr-x 1 norore norore 1071028  1 mai   18:33 13.ogg
-rw-r-xr-x 1 norore norore 2587419  1 mai   18:33 blocks.ogg
-rw-r-xr-x 1 norore norore 1286636  1 mai   18:33 cat.ogg
-rw-r-xr-x 1 norore norore 1379756  1 mai   18:33 chirp.ogg
-rw-r-xr-x 1 norore norore 1285938  1 mai   18:33 far.ogg
-rw-r-xr-x 1 norore norore 1430016  1 mai   18:33 mall.ogg
-rw-r-xr-x 1 norore norore  663709  1 mai   18:33 mellohi.ogg
-rw-r-xr-x 1 norore norore 1558180  1 mai   18:33 strad.ogg
-rw-r-xr-x 1 norore norore 1845255  1 mai   18:33 wait.ogg
-rw-r-xr-x 1 norore norore 1987588  1 mai   18:33 ward.ogg

Le mot de la fin

J’espère que ces modestes exemples vous aurons donné un aperçu des possibilités de la commande find et que vous aurez moins peur de la tester ! Pour l’instant je fais un usage classique de cette commande, mais quand je vois le nombre de lignes du manuel, je sais que je ne suis pas là d’en avoir fait le tour, et que je dois sûrement passer à côté de certaines fonctionnalités encore plus impressionnantes !

Et vous, utilisez-vous cette super commande ? Si oui, pour quels usages ? Quels sont vos tuyaux pour aider une personne à se lancer sur son utilisation ?


Source de l’image d’accroche : Des lunettes posées sur une page d’un livre avec du texte surligné. Photographié par Boesmantjie, sous licence Pixabay sur Pixabay