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


12

J'ai un dossier avec un tas de sous-dossiers, ces dossiers ont été asciidoctorclassés avec .adocextension.

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'à présent, je suis venu avec ceci en utilisant entr :

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

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

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

Des idées sur la façon dont je pourrais implémenter ce processus d'automatisation pour tous les sous-dossiers?


Réponses:


17

Linux fournit une interface agréable pour surveiller tous les événements du système de fichiers comme la création, la modification et la suppression de fichiers. L'interface est une inotifyfamille d'appels système, les utilitaires de l'espace utilisateur exploitant ces appels sont fournis par le inotify-toolspackage dans Ubuntu (disponible sur 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-toolsfournit inotifywaitet les inotifywatchbinaires, nous avons besoin du premier.


Vous souhaitez donc exécuter la commande asciidoctor -q some_filelorsqu'un .adocfichier est modifié ( some_filesera remplacé par celui-ci), si vous supposez que vos .adocfichiers se trouvent dans le répertoire /foo/bar, vous pouvez définir la surveillance:

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

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

  • --event modify, nous ne nous intéressons qu'aux modifyévénements c'est-à-dire lorsqu'un fichier est modifié. D'autres valeurs possibles incluent open, closeetc.

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

  • /foo/bar/*.adocsera étendu à tous les .adocfichiers du /foo/barrépertoire


Maintenant, ce qui précède vous montrera le nom du fichier à chaque modification, maintenant pour exécuter la commande sur le nom de fichier (en supposant que la commande prend des 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 uniquement les fichiers souhaités. Ici, configurer la montre de manière récursive ( -r) sur le répertoire /foo/baret utiliser greppour filtrer uniquement les .adocfichiers:

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 se %wrésout en nom de répertoire, nous devons %fdonc obtenir le nom du fichier. Tout en regardant des fichiers, %fse résoudrait à une chaîne vide.

Notez que vous pouvez également exécuter inotifywaiten -dmode daemon ( ), vous pouvez également scripter le tout, et / ou exécuter en arrière-plan, et / ou jouer avec d'autres options.

Vous pouvez également la remplacer asciidoctorpar n'importe quelle autre commande de votre choix, si vous le souhaitez.

Cochez man inotifywaitpour avoir plus d'idée.


Merci ça a marché. J'ai aussi quelque chose de similaire pour OSX. mais je suppose que ce n'est pas le bon endroit pour demander.
son

@bran Oui, à mon humble avis allez à UL , vous pouvez l'utiliser comme référence.
heemayl

Excellente réponse, juste une correction mineure. -q rend le programme "moins verbeux", -qq (double q) le rend complètement silencieux sauf pour les erreurs fatales.
jotadepicas

4

L'utilisation inotifywaitest l'approche typique, mais il existe également un utilitaire distinct appelé inotify-hookablequi 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 se fermer après avoir déclenché la commande une fois; Je ne vois pas d'option pour une surveillance continue, 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, récursivement, et des options pour ignorer les fichiers / chemins.


inotify-hookable ne se ferme pas après avoir exécuté la commande pour moi. Hmm
Max

inotify-hookable est installé à partir d'un package différent:sudo apt-get install inotify-hookable
Bruno Silvano

3

Il existe de nombreux outils, surtout si vous recherchez dans votre référentiel

apt-cache search monitor | grep file

ce qui nous donne de nombreux outils. Mais vous n'avez pas à les tester parce que je l'ai fait.

J'ai testé ces outils et bien d'autres:

  • inotifier
  • fswatch
  • filewatch
  • échantillon
  • fichierschangés
  • entr

Parmi ces outils, j'en ai trouvé trois utiles et fiables:

  • direvent | GNU écrit en C
  • iwatch | en Perl
  • fsniper

Et entre ces trois, le direvent est le meilleur sans aucun doute.

Il est si utile et fiable à utiliser que je l'ai utilisé pour un simple pipeline avec mes microservices.

direvent.conf fichier pour regarder

syslog {
    facility local0;
    tag "direvent";
    print-priority yes;
}

watcher {
    path /var/www/html/ir/jsfun/build/react recursive;
    file "*.js";
    event write;
    command "/usr/bin/xdotool search --onlyvisible  --class firefox key F5";
    option (stdout, stderr, wait);
}

Ce n'est qu'un des fichiers de configuration que j'ai dans lequel chaque fois qu'il y a un changement pour l' écriture, cette commande est exécutée - ce qui pourrait également être un script .

Pas besoin d'utiliser de whileboucle ou autre.


traits

  • regarder récursivement un répertoire
  • peut être exécuté en premier plan ou en arrière - plan en tant que démon
  • portable. Je l'ai sur Ubuntu ainsi que sur le serveur CentOS7
  • rapport sur le nom de fichier
  • expression régulière pour prendre en charge la correspondance de fichiers
  • observation de fichiers multiples (regardez plus qu'un seul type de fichier)
  • synchroniser l'exécution des commandes (si nous avons plusieurs observateurs)
  • gestion de Syslog (connectez-vous à Syslog si nous voulons)
  • CLI facile et bon et conception de fichiers de configuration pour travailler avec

Développé par Sergey Poznyakoff .


L'installation

sudo apt install direvent

Mais l'installer en utilisant son code source est assez facile et simple, ce qui vous donne la dernière version (actuellement: 5.1).


-3

Eh bien, je recommande ce qui suit.

#!/bin/bash
#Script
for SRC in *.adoc; 
      do
      asciidoctor -q $SRC
  done

1
OP veut exécuter la commande uniquement lorsque des modifications sont apportées ..
heemayl
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.