web-dev-qa-db-fra.com

Script Bash pour surveiller le changement de fichier et exécuter la commande

J'ai un dossier avec un groupe de sous-dossiers, ces dossiers ont asciidoctor formatated classé avec l'extension .adoc.

Chaque fois que je modifie des fichiers (ce qui est souvent le cas), je dois exécuter

asciidoctor -q filename.adoc

pour le compiler au format HTML.

J'essaie d'automatiser le processus. Jusqu'ici, je suis venu avec cela en utilisant entr :

ls *.adoc | entr asciidoctor -q *.adoc

mais ne fonctionne qu'avec le dossier existant pas pour les sous-dossiers. J'ai essayé cette variante, mais ça ne marche pas:

find . -name '*.adoc' | entr asciidoctor -q *.adoc

Des idées sur la manière dont je pourrais implémenter ce processus automatisé pour tous les sous-dossiers?

9
bran

Linux fournit une interface agréable pour surveiller tous les événements du système de fichiers, tels que la création, la modification et la suppression de fichiers. L'interface est une famille d'appels système inotifyname__; les utilitaires utilisateur utilisant ces appels sont fournis par le paquetage inotify-tools dans Ubuntu (disponible dans le référentiel de l'univers). Si vous ne l'avez pas déjà, installez le par:

Sudo apt-get install inotify-tools

inotify-tools fournit les binaires inotifywaitet inotifywatchname__, nous avons besoin du premier.


Donc, vous voulez exécuter la commande asciidoctor -q some_file quand un fichier .adoc est modifié (some_file sera remplacé par celui-ci), si donc vos fichiers .adoc sont dans le répertoire /foo/bar, vous pouvez définir la surveillance:

inotifywait -qm --event modify --format '%w' /foo/bar/*.adoc
  • -q active le mode silencieux, aucune information de inotifywaitelle-même

  • -m active le mode moniteur, sinon il se fermera après le premier événement

  • --event modify, nous ne sommes intéressés que par l’événement modifyi.e. lorsqu'un fichier est modifié. Les autres valeurs possibles incluent openname__, closeetc.

  • --format %w, nous voulons uniquement le nom de fichier modifié plutôt que d'autres informations, car nous utiliserons le nom de fichier comme entrée d'une autre commande.

  • /foo/bar/*.adoc sera étendu à tous les fichiers .adoc du répertoire /foo/bar


Maintenant, ce qui précède vous montrera le nom du fichier chaque fois que vous en modifiez un, exécutez maintenant la commande sur le nom du fichier (en supposant que la commande prenne les arguments via STDIN):

inotifywait -qm --event modify --format '%w' /foo/bar/*.adoc | asciidoctor -q

Vous pouvez également configurer une surveillance récursive sur le répertoire. Vous devrez ensuite utiliser greppour filtrer les fichiers souhaités uniquement. Ici, vous définissez la montre de manière récursive (-r) dans le répertoire /foo/bar et utilisez greppour filtrer uniquement les fichiers .adoc:

inotifywait -qrm --event modify --format '%w%f' /foo/bar | grep '\.adoc$' | asciidoctor -q

Lorsque vous regardez des répertoires, le spécificateur de format de sortie %w est résolu en nom de répertoire. Nous avons donc besoin de %f pour obtenir le nom du fichier. Tout en regardant les fichiers, %f résoudrait le problème en une chaîne vide.

Notez que vous pouvez également exécuter inotifywaiten mode démon (-d), vous pouvez également créer un script complet et/ou exécuter en arrière-plan et/ou jouer avec d'autres options.

De même, vous pouvez remplacer asciidoctorpar toute autre commande de votre choix, si vous le souhaitez.

Vérifiez man inotifywait pour avoir plus d’idées.

14
heemayl

L'approche typique est inotifywait, mais il existe également un utilitaire séparé appelé inotify-hookable qui vous permet simplement d'exécuter une commande lorsqu'un fichier (ou répertoire) change:

inotify-hookable -f filename.adoc -c 'asciidoctor -q filename.adoc'

Il semble sortir après avoir déclenché la commande une fois; Je ne vois pas d'option pour regarder en continu, vous pouvez donc faire quelque chose comme:

while true; do
    inotify-hookable -f filename.adoc -c 'asciidoctor -q filename.adoc'
    echo "== $(date) : executed, continuing to monitor..."
done

Notez qu'il existe des options pour surveiller plusieurs fichiers ou un répertoire, de manière récursive, et des options pour ignorer les fichiers/chemins.

3
michael