Script di Bash per monitorare la modifica dei file ed eseguire il comando


12

Ho una cartella con un sacco di sottocartelle, queste cartelle hanno asciidoctorformulato con .adocestensione.

Ogni volta che ho apportato modifiche ai file (che è spesso) devo eseguire

asciidoctor -q filename.adoc

per compilarlo in formato HTML.

Sto cercando di automatizzare il processo. finora sono arrivato con questo usando entr :

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

ma funziona solo con la cartella esistente non per le sottocartelle. Ho provato questa variante, ma non funziona:

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

Qualche idea su come potrei implementare questo processo automatizzato per tutte le sottocartelle?


1
Possibile duplicato di Come rilevate le modifiche ai file
Anwar

Risposte:


17

Linux fornisce una bella interfaccia per monitorare tutti gli eventi del file system come la creazione, la modifica, la rimozione di file. L'interfaccia è una inotifyfamiglia di chiamate di sistema, le utility di userspace che sfruttano queste chiamate sono fornite dal inotify-toolspacchetto in Ubuntu (disponibile sul repository dell'universo). Se non lo hai già, installa:

sudo apt-get install inotify-tools

inotify-toolsfornisce inotifywaite inotifywatchbinari, abbiamo bisogno del primo.


Quindi vuoi eseguire il comando asciidoctor -q some_filequando qualsiasi .adocfile viene modificato ( some_fileverrà sostituito da quello), se così assumendo che i tuoi .adocfile siano nella directory /foo/bar, puoi impostare l'orologio:

inotifywait -qm --event modify --format '%w' /foo/bar/*.adoc
  • -qabilita la modalità silenziosa, nessuna informazione da inotifywaitsola

  • -m abilita la modalità monitor, altrimenti uscirà dopo il primo evento

  • --event modify, siamo interessati solo modifyall'evento, ad esempio quando un file viene modificato. Altri possibili valori includono open, closeecc.

  • --format %w, vogliamo solo il nome del file che viene modificato anziché un mucchio di altre informazioni poiché useremo il nome del file come input per un altro comando

  • /foo/bar/*.adocverrà espanso in tutti i .adocfile nella /foo/bardirectory


Ora quanto sopra ti mostrerà il nome del file ogni qualvolta viene modificato, ora per eseguire il comando sul nome del file (supponendo che il comando accetta argomenti tramite STDIN):

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

È inoltre possibile impostare un orologio ricorsivo sulla directory, quindi sarà necessario utilizzare grepper filtrare solo i file desiderati. Qui impostando watch ricorsivamente ( -r) sulla directory /foo/bare usando grepper filtrare solo i .adocfile:

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

Quando si guardano le directory, l'identificatore del formato di output si %wrisolve nel nome della directory, quindi è necessario %fottenere il nome del file. Durante la visione di file, %frisolverebbe svuotare la stringa.

Nota che puoi anche eseguire inotifywaitin -dmodalità demone ( ), puoi anche scrivere tutto, e / o eseguire in background e / o giocare con altre opzioni.

Inoltre, se lo desideri, puoi sostituirlo asciidoctorcon qualsiasi altro comando di tua scelta.

Controlla man inotifywaitper avere più idee.


Grazie ha funzionato. Ho anche qualcosa di simile per OSX. ma suppongo che questo non sia il posto giusto per chiedere.
crusca

@bran Sì, IMHO vai a UL , puoi usarlo come riferimento.
heemayl

Ottima risposta, solo una piccola correzione. -q rende il programma "meno dettagliato", -qq (doppio q) lo rende completamente silenzioso ad eccezione di errori fatali.
jotadepicas,

4

L'utilizzo inotifywaitè l'approccio tipico, ma esiste anche un'utilità separata chiamata inotify-hookableche consente di eseguire un comando quando cambia un file (o directory):

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

Sembra uscire dopo aver attivato il comando una volta; Non vedo un'opzione per l'osservazione continua, quindi potresti fare qualcosa del tipo:

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

Nota: esistono opzioni per monitorare più file o una directory, in modo ricorsivo, e opzioni per ignorare file / percorsi.


inotify-hookable non si chiude dopo aver eseguito il comando per me. Hmm
Max

inotify-hookable è installato da un pacchetto diverso:sudo apt-get install inotify-hookable
Bruno Silvano,

3

Esistono molti strumenti là fuori, specialmente se cerchi nel tuo repository

apt-cache search monitor | grep file

che ci dà molti strumenti. Ma non devi provarli perché l'ho fatto.

Ho testato questi strumenti e molti altri:

  • inotify
  • fswatch
  • fileWATCH
  • swatch
  • fileschanged
  • entr

Tra questi strumenti ne ho trovati tre utili e affidabili:

  • direvente | GNU scritto in C
  • iwatch | in Perl
  • fsniper

E tra questi tre, il direvent è il migliore senza dubbio.

È così utile e affidabile da usare che l'ho usato per una semplice pipeline con i miei microservizi che ho.

direvent.conf file per la visione

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

Questo è solo uno dei file di configurazione che ho in cui ogni volta che c'è una modifica per la scrittura, questo comando viene eseguito, che potrebbe anche essere uno script .

Non c'è bisogno di usare whileloop o altre cose.


Caratteristiche

  • guardare ricorsivamente una directory
  • può essere eseguito in primo piano o in background come demone
  • portatile. Ce l'ho su Ubuntu e sul server CentOS7
  • rapporto sul nome del file
  • regex per supportare la corrispondenza dei file
  • guardare file mulit (guarda più di un solo tipo di file)
  • sincronizzare l'esecuzione dei comandi (se abbiamo multi-watcher)
  • gestione syslog (accedere a syslog se lo si desidera)
  • CLI semplice e buona e file di configurazione con cui lavorare

Sviluppato da Sergey Poznyakoff .


Installazione

sudo apt install direvent

Ma installarlo usando il suo codice sorgente è abbastanza semplice e diretto che ti dà l'ultima versione (in questo momento è: 5.1).


-3

Bene, raccomando quanto segue.

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

1
OP vuole eseguire il comando solo quando vengono apportate modifiche.
heemayl
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.