22

I have a folder with a bunch of subfolders, these folders have asciidoctor formated filed with .adoc extension.

Every time I made changes to files (which is often) I need to run

asciidoctor -q filename.adoc

to compile it into HTML format.

I am trying to automate the process. so far I have come with this using entr:

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

but only works with existing folder not for subfolders. I have tried this variation, but it doesn't work:

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

Any ideas how I could implement this automate process for all the subfolders?

1

4 Answers 4

29

Linux provides a nice interface for monitoring all file system events like creating, modifying, removing files. The interface is inotify family of system calls, the userspace utilities leveraging these calls are provided by the inotify-tools package in Ubuntu (available on the universe repository). If you don't have it already, install by:

sudo apt-get install inotify-tools

inotify-tools provides inotifywait and inotifywatch binaries, we need the first one.


So you want to run the command asciidoctor -q some_file when any .adoc file is modified (some_file will replaced by that), if so assuming your .adoc files are in directory /foo/bar, you can set the watch:

inotifywait -qm --event modify --format '%w' /foo/bar/*.adoc
  • -q enables the quiet mode, no info from inotifywait itself

  • -m enables monitor mode, otherwise it will exit after the first event

  • --event modify, we are only interested in modify event i.e. when a file is modified. Other possible values include open, close etc.

  • --format %w, we only want the file name that is modified rather than bunch of other info as we will use the file name as input to another command

  • /foo/bar/*.adoc will be expanded to all .adoc files under /foo/bar directory


Now the above will show you the filename whenever any is modified, now to run the command on the filename (assuming the command takes arguments via STDIN):

inotifywait -qm --event modify --format '%w' /foo/bar/*.adoc | while read -r file ; do
    asciidoctor -q "$file"
done

You can also setup a recursive watch on the directory, you will then need to use grep to filter the desired files only. Here setting the watch recursively (-r) on directory /foo/bar and using grep to filter only .adoc files:

inotifywait -qrm --event modify --format '%w%f' /foo/bar | grep '\.adoc$' | while read -r file ; do
    asciidoctor -q "$file"
done

When watching directories the output format specifier %w resolves to the directory name, so we need %f to get the file name. While watching files, %f would resolve to empty string.

Note that, you can also run inotifywait in daemon (-d) mode, you can also script the whole thing, and/or run in background, and/or play with it more other options.

Also, you can replace asciidoctor with any other command of your choice, if you want.

Check man inotifywait to get more idea.

3
  • Thanks it worked. I also something similar for OSX. but I guess this is not the right place to ask.
    – bran
    Aug 31, 2016 at 21:06
  • @bran Yes, IMHO go to UL, you can use this as a reference.
    – heemayl
    Aug 31, 2016 at 21:07
  • 1
    Great answer, just a minor correction. -q makes the program "less verbose", -qq (double q) makes it completely silent except for fatal errors. Dec 6, 2018 at 21:37
11

There are many tools out there, specially if you search through your repository

apt-cache search monitor | grep file

which gives us many tools. But you do not have to test them because I did that.

I have tested these tools and many others: inotifywait (from inotify-tools), fswatch, filewatch, swatch, fileschanged, and entr.

Among these tools I found three of them useful and reliable:

And from these three, the direvent is the best with no doubt.

direvent

It is so useful and reliable to use that I have used it for a simple pipeline with my microservices I have.

direvent.conf file for watching

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

This is just one of the config files I have in which whenever there is a change for write then this command is executed - which could be a script as well.

No need to use while loop or other stuff.


features

  • recursively watching a directory
  • can be run in foreground or background as a daemon
  • portable. I have it in Ubuntu as well as CentOS7 server
  • file name report
  • regex to support file matching
  • mulit-file watching (watch more then just one type of file)
  • synchronize commands execution (if we have multi-watcher)
  • syslog handling (log to syslog if we want)
  • easy and good CLI and config file design to work with

Developed by Sergey Poznyakoff.


Installing

sudo apt install direvent

But installing it using its source code is pretty easy and straightforward which gives you the last version (right now is: 5.1).

3
  • 1
    It would be useful if each tool was a separate post, so that they could be voted on separately.
    – Flimm
    Jan 25, 2023 at 13:53
  • 1
    iwatch hasn't been updated since 2009. I found it to be buggy #2003873
    – Flimm
    Jan 25, 2023 at 15:01
  • 1
    fileschanged has been removed from Ubuntu repos.
    – Flimm
    Jan 25, 2023 at 15:09
8

Using inotifywait is the typical approach, but there's also a separate utility called inotify-hookable that just lets you run a command when a file (or directory) changes:

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

It seems to exit after triggering the command once; I don't see an option for continous watching, so you could do something like:

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

Note there are options to monitor several files or a directory, recursively, and options to ignore files/paths.

2
  • 3
    inotify-hookable does not exit after running the command for me. Hmm
    – Max
    Feb 12, 2018 at 15:14
  • 1
    inotify-hookable is installed from a different package: sudo apt-get install inotify-hookable Nov 5, 2019 at 10:54
-5

Well I recommend the following.

#!/bin/bash
#Script
for SRC in *.adoc; 
      do
      asciidoctor -q $SRC
  done
1
  • 3
    OP wants to run the command only when modifications are made..
    – heemayl
    Aug 31, 2016 at 18:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .