Script Bash para monitorar a alteração de arquivos e executar o comando


12

Eu tenho uma pasta com um monte de subpastas, essas pastas foram asciidoctorformatadas arquivadas com .adocextensão.

Toda vez que faço alterações nos arquivos (o que geralmente ocorre), preciso executar

asciidoctor -q filename.adoc

para compilá-lo no formato HTML.

Estou tentando automatizar o processo. até agora eu vim com isso usando entr :

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

mas funciona apenas com a pasta existente, não nas subpastas. Eu tentei essa variação, mas não funciona:

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

Alguma idéia de como eu poderia implementar esse processo automatizado para todas as subpastas?


Respostas:


17

O Linux fornece uma interface agradável para monitorar todos os eventos do sistema de arquivos, como criar, modificar e remover arquivos. A interface é uma inotifyfamília de chamadas do sistema, os utilitários de espaço do usuário que utilizam essas chamadas são fornecidos pelo inotify-toolspacote no Ubuntu (disponível no repositório do universo). Se você ainda não o possui, instale por:

sudo apt-get install inotify-tools

inotify-toolsfornece inotifywaite inotifywatchbinários, precisamos do primeiro.


Portanto, você deseja executar o comando asciidoctor -q some_filequando qualquer .adocarquivo for modificado ( some_fileserá substituído por isso); se houver, assumindo que seus .adocarquivos estão no diretório /foo/bar, você pode definir o relógio:

inotifywait -qm --event modify --format '%w' /foo/bar/*.adoc
  • -qativa o modo silencioso, sem informações por inotifywaitsi só

  • -m ativa o modo monitor, caso contrário, ele será encerrado após o primeiro evento

  • --event modify, estamos interessados ​​apenas no modifyevento, ou seja, quando um arquivo é modificado. Outros valores possíveis incluem open, closeetc.

  • --format %w, queremos apenas o nome do arquivo modificado em vez de várias outras informações, pois usaremos o nome do arquivo como entrada para outro comando

  • /foo/bar/*.adocserá expandido para todos os .adocarquivos no /foo/bardiretório


Agora, o acima mostrará o nome do arquivo sempre que qualquer um for modificado, agora para executar o comando no nome do arquivo (assumindo que o comando receba argumentos via STDIN):

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

Você também pode configurar uma inspeção recursiva no diretório, depois precisará usar greppara filtrar apenas os arquivos desejados. Aqui, configure o relógio recursivamente ( -r) no diretório /foo/bare use-o greppara filtrar apenas .adocarquivos:

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

Ao assistir aos diretórios, o especificador de formato de saída é %wresolvido para o nome do diretório, portanto, precisamos %fobter o nome do arquivo. Enquanto assistia arquivos, %fresolveria esvaziar a string.

Observe que, você também pode executar inotifywaitno modo daemon ( -d), também pode escrever a coisa toda e / ou executar em segundo plano e / ou brincar com ela mais outras opções.

Além disso, você pode substituir asciidoctorpor qualquer outro comando de sua escolha, se desejar.

Marque man inotifywaitpara ter mais ideia.


Graças funcionou. Eu também algo semelhante para OSX. mas acho que esse não é o lugar certo para perguntar.
far

@ran Sim, IMHO ir para UL , você pode usar isso como uma referência.
heemayl

Ótima resposta, apenas uma pequena correção. -q torna o programa "menos detalhado", -qq (q duplo) o torna completamente silencioso, exceto por erros fatais.
Jotadepicas

4

Usar inotifywaité a abordagem típica, mas também há um utilitário separado chamado inotify-hookableque permite executar um comando quando um arquivo (ou diretório) é alterado:

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

Parece sair depois de disparar o comando uma vez; Não vejo uma opção para assistir continuamente, então você pode fazer algo como:

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

Observe que existem opções para monitorar vários arquivos ou um diretório, recursivamente, e opções para ignorar arquivos / caminhos.


O inotify-hookable não sai depois de executar o comando para mim. Hmm
Max

inotify-hookable é instalado a partir de um pacote diferente:sudo apt-get install inotify-hookable
de Bruno Silvano

3

Existem muitas ferramentas por aí, especialmente se você pesquisar no seu repositório

apt-cache search monitor | grep file

o que nos dá muitas ferramentas. Mas você não precisa testá-los porque eu fiz isso.

Eu testei essas ferramentas e muitas outras:

  • inotify
  • fswatch
  • filewatch
  • amostra
  • modificado
  • entr

Entre essas ferramentas, encontrei três delas úteis e confiáveis:

  • direvent | GNU escrito em C
  • iwatch | em Perl
  • fsniper

E entre esses três, o direvent é o melhor, sem dúvida.

É tão útil e confiável de usar que usei para um pipeline simples com meus microsserviços que tenho.

direvent.conf arquivo para assistir

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

Este é apenas um dos arquivos de configuração que eu tenho e, sempre que há uma alteração na gravação , esse comando é executado - o que também pode ser um script .

Não há necessidade de usar whileloop ou outras coisas.


recursos

  • assistindo recursivamente a um diretório
  • pode ser executado em primeiro plano ou em segundo plano como um daemon
  • portátil. Eu o tenho no Ubuntu, bem como no servidor CentOS7
  • relatório de nome de arquivo
  • regex para suportar a correspondência de arquivos
  • observação de arquivos mulit (assista a mais do que apenas um tipo de arquivo)
  • sincronizar a execução de comandos (se tivermos vários observadores)
  • manipulação de syslog (log para syslog, se quisermos)
  • fácil e bom design de arquivo de configuração e CLI para trabalhar com

Desenvolvido por Sergey Poznyakoff .


Instalando

sudo apt install direvent

Mas instalá-lo usando seu código-fonte é bastante fácil e direto, o que fornece a última versão (agora é: 5.1).


-3

Bem, eu recomendo o seguinte.

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

1
OP quer executar o comando somente quando forem feitas modificações ..
heemayl
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.