Скрипт Bash для отслеживания изменений файла и выполнения команды


12

У меня есть папка с кучей подпапок, эти папки asciidoctorотформатированы с .adocрасширением.

Каждый раз, когда я вносил изменения в файлы (что часто), мне нужно запустить

asciidoctor -q filename.adoc

скомпилировать его в формат HTML.

Я пытаюсь автоматизировать процесс. до сих пор я пришел с этим с помощью entr :

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

но работает только с существующей папкой не для подпапок. Я пробовал этот вариант, но он не работает:

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

Любые идеи, как я мог бы реализовать этот процесс автоматизации для всех вложенных папок?


Ответы:


17

Linux предоставляет удобный интерфейс для мониторинга всех событий файловой системы, таких как создание, изменение, удаление файлов. Интерфейс представляет собой inotifyсемейство системных вызовов, утилиты пользовательского пространства, использующие эти вызовы, предоставляются inotify-toolsпакетом в Ubuntu (доступно в репозитории юниверсов). Если у вас его еще нет, установите:

sudo apt-get install inotify-tools

inotify-toolsпредоставляет inotifywaitи inotifywatchдвоичные файлы, нам нужен первый.


Таким образом, вы хотите выполнить команду, asciidoctor -q some_fileкогда какой-либо .adocфайл будет изменен ( some_fileбудет заменен этим), если, если это так, если ваши .adocфайлы находятся в каталоге /foo/bar, вы можете установить часы:

inotifywait -qm --event modify --format '%w' /foo/bar/*.adoc
  • -qвключает тихий режим, никакой информации от inotifywaitсебя

  • -m включает режим мониторинга, иначе он выйдет после первого события

  • --event modify, нас интересует только modifyсобытие, то есть когда файл изменяется. Другие возможные значения включают openи closeт. Д.

  • --format %w, мы хотим, чтобы имя файла было изменено, а не куча другой информации, так как мы будем использовать имя файла в качестве ввода для другой команды

  • /foo/bar/*.adocбудет расширен до всех .adocфайлов в /foo/barкаталоге


Теперь вышеприведенное покажет вам имя файла, когда что-либо будет изменено, теперь для запуска команды с именем файла (при условии, что команда принимает аргументы через STDIN):

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

Вы также можете установить рекурсивное наблюдение за каталогом, которое вам нужно будет использовать grepдля фильтрации только нужных файлов. Здесь установка watch recursively ( -r) на каталог /foo/barи использование grepдля фильтрации только .adocфайлов:

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

При просмотре каталогов спецификатор выходного формата %wразрешается в имя директории, поэтому нам нужно %fполучить имя файла. При просмотре файлов %fразрешил бы пустую строку.

Обратите внимание, что вы также можете работать inotifywaitв режиме daemon ( -d), вы также можете создавать сценарии целиком и / или работать в фоновом режиме, и / или играть с другими дополнительными параметрами.

Кроме того, вы можете заменить asciidoctorлюбую другую команду по вашему выбору, если хотите.

Проверьте, man inotifywaitчтобы получить больше идей.


Спасибо, это сработало. У меня тоже что-то похожее на OSX. но я думаю, что это не то место, чтобы спрашивать.
отруби

@bran Да, ИМХО перейти на UL , вы можете использовать это как ссылку.
Heemayl

Отличный ответ, просто небольшая поправка. -q делает программу "менее многословной", -qq (double q) делает ее полностью бесшумной, за исключением фатальных ошибок.
Jotadepicas

4

Использование inotifywait- это типичный подход, но есть и отдельная утилита, inotify-hookableкоторая позволяет запускать команду при изменении файла (или каталога):

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

Кажется, чтобы выйти после запуска команды один раз; Я не вижу опции для непрерывного просмотра, поэтому вы можете сделать что-то вроде:

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

Обратите внимание, что существуют опции для рекурсивного мониторинга нескольких файлов или каталогов, а также опции для игнорирования файлов / путей.


inotify-hookable не выходит после запуска команды для меня. Хм
Макс

inotify-hookable устанавливается из другого пакета:sudo apt-get install inotify-hookable
Бруно Сильвано

3

Есть много инструментов, особенно если вы ищете в своем хранилище

apt-cache search monitor | grep file

что дает нам много инструментов. Но вам не нужно проверять их, потому что я это сделал.

Я проверил эти инструменты и многие другие:

  • Inotify
  • fswatch
  • FileWatch
  • образчик ткани
  • fileschanged
  • ENTR

Среди этих инструментов я нашел три из них полезных и надежных:

  • страшный | GNU написано на C
  • iwatch | в Perl
  • fsniper

И между этими тремя, без сомнения , лучшая - лучшая.

Он настолько полезен и надежен, что я использовал его для простого конвейера с моими микросервисами, которые у меня есть.

direvent.conf файл для просмотра

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

Это всего лишь один из моих конфигурационных файлов, в которых всякий раз, когда происходит изменение записи, выполняется эта команда, что также может быть сценарием .

Нет необходимости использовать whileпетли или другие вещи.


функции

  • рекурсивно просматривая каталог
  • может быть запущен на переднем или заднем плане в качестве демона
  • портативный. У меня это есть в Ubuntu и на сервере CentOS7
  • отчет об имени файла
  • регулярное выражение для поддержки сопоставления файлов
  • просмотр нескольких файлов (просмотр более одного типа файла)
  • синхронизировать выполнение команд (если у нас есть несколько наблюдателей)
  • обработка системного журнала (вход в системный журнал, если мы хотим)
  • простой и хороший CLI и дизайн файла конфигурации для работы с

Разработано Сергеем Позняковым .


Установка

sudo apt install direvent

Но установить его, используя его исходный код, довольно легко и просто, что дает вам последнюю версию (прямо сейчас: 5.1).


-3

Ну, я рекомендую следующее.

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

1
ОП хочет выполнить команду только после внесения изменений ..
Химейл
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.