KeiruaProd

I help my clients acquire new users and make more money with their web businesses. I have ten years of experience with SaaS projects. If that’s something you need help with, we should get in touch!
< Back to article list

Agir lors des modifications sur un fichier

Effectuer une action lorsqu’un fichier est modifié est une tâche qui revient de temps en temps.

J’ai utilisé 3 manières pour la résoudre:

inotifywait

inotifywait fait partie des outils inotify-tools. C’est bancal, mais ca marche.

Pour l’installer sur un système d’exploitation basé sur Debian, comme Ubuntu :

sudo apt-get install inotify-tools

Pour surveiller les événements de création de fichier dans le répertoire courant, vous pouvez utiliser la commande suivante :

inotifywait -m -e create .

(pour le moment, cette commande surveillera en continu les événements de création de fichier dans le répertoire courant, et affichera chaque événement dès qu’il se produira, on agira dessus un peu plus tard)

On peut surveiller plusieurs événements en même temps, ici création, modification et suppression de fichier :

inotifywait -m -e create -e modify -e delete .

L’intérêt, c’est d’ utiliser inotifywait en combinaison d’autres commandes pour automatiser certaines tâches. Par exemple, si vous souhaitez surveiller un répertoire et lancer une commande chaque fois qu’un fichier est créé ou modifié, vous pouvez utiliser la syntaxe suivante :

inotifywait -m -e create -e modify /chemin/vers/le/répertoire | while read path action file; do commande; done

Exemple concret dans un projet récent:

#/bin/bash
inotifywait -m posts/ stylesheets/ \
	-e create -e moved_to -e modify | while read datetime dir filename event; do
		cargo run --bin compile
		# or pretty much what you want to do when something changes.
	done

entr

entr est un wrapper autour d’inotify, la commande est différente mais le résultat est le même:

while true; do \
	ls -d posts/* stylesheets/* index.html | entr -cd make ;\
done

Code sur mesure

En rust, on peut utiliser la crate notify.

Voici un exemple inspiré de leur hot-reloading:

pub async fn watch_and_serve() -> Result<(), std::io::Error> {
    let _ = compile_static_website();
    let mut watcher: RecommendedWatcher = notify::recommended_watcher(|res| match res {
        Ok(event) => {
            println!("event: {:?}", event);
            let _ = compile_static_website();
        }
        Err(e) => println!("watch error: {:?}", e),
    })
    .unwrap();
    let directories = ["posts", "stylesheets", "templates"];
    for dir in directories {
        let _ = watcher.watch(Path::new(dir), RecursiveMode::Recursive);
    }

    serve().await
}