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 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
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
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
}