Как запустить скрипт оболочки, когда файл или каталог меняется?

StackOverflow https://stackoverflow.com/questions/4060212

  •  27-09-2019
  •  | 
  •  

Вопрос

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

Как я могу легко сделать это?

Это было полезно?

Решение

Использовать inotify-tools..

Другие советы

Я использую этот скрипт для запуска скрипта сборки на изменениях дерева каталога:

#!/bin/bash -eu
DIRECTORY_TO_OBSERVE="js"      # might want to change this
function block_for_change {
  inotifywait --recursive \
    --event modify,move,create,delete \
    $DIRECTORY_TO_OBSERVE
}
BUILD_SCRIPT=build.sh          # might want to change this too
function build {
  bash $BUILD_SCRIPT
}
build
while block_for_change; do
  build
done

Использует inotify-tools. Отказ Проверить inotifywait человек страницы Для того, как настроить то, что запускает сборку.

Вы можете попробовать entr Инструмент для запуска произвольных команд при изменении файлов. Пример для файлов:

$ ls -d * | entr sh -c 'make && make test'

или:

$ ls *.css *.html | entr reload-browser Firefox

или распечатать Changed! Когда файл file.txt сохраняется:

$ echo file.txt | entr echo Changed!

Для каталогов используются -d, но вы использовали его в петле, например:

while true; do find path/ | entr -d echo Changed; done

или:

while true; do ls path/* | entr -pd echo Changed; done

Проверьте демон монитора файловой системы ядра

http://freshmeat.net/projects/kfsmd/

Вот как-к:

http://www.linux.com/archive/feature/124903.

Как уже упоминалось, Intify-Tools, вероятно, является лучшей идеей. Однако, если вы программируете для удовольствия, вы можете попробовать и зарабатывать хакер XPS путем разумного применения хвост -f. .

Как насчет этого скрипта? Использует команду «stat», чтобы получить время доступа файла и запускает команду всякий раз, когда есть изменение времени доступа (всякий раз, когда файл доступа к).

#!/bin/bash

while true

do

   ATIME=`stat -c %Z /path/to/the/file.txt`

   if [[ "$ATIME" != "$LTIME" ]]

   then

       echo "RUN COMMNAD"
       LTIME=$ATIME
   fi
   sleep 5
done

Вот еще один вариант: http://fileschanged.sourceforge.net/

См. Особенно «Пример 4», который «контролирует каталог и архивы любые новые или измененные файлы».

inotifywait может удовлетворить вас.

Вот общий образец для него:

inotifywait -m /path -e create -e moved_to -e close_write | # -m is --monitor, -e is --event
    while read path action file; do
        if [[ "$file" =~ .*rst$ ]]; then             # if suffix is '.rst'
            echo ${path}${file} ': '${action}        # execute your command
            echo 'make html'
            make html
        fi
    done

Просто для целей отладки, когда я пишу скрипт оболочки и хочу, чтобы он запустился на сохранении, я использую это:

#!/bin/bash
file="$1" # Name of file
command="${*:2}" # Command to run on change (takes rest of line)
t1="$(ls --full-time $file | awk '{ print $7 }')" # Get latest save time
while true
do
  t2="$(ls --full-time $file | awk '{ print $7 }')" # Compare to new save time
  if [ "$t1" != "$t2" ];then t1="$t2"; $command; fi # If different, run command
  sleep 0.5
done

Запустите его как

run_on_save.sh myfile.sh ./myfile.sh arg1 arg2 arg3

Редактировать: Выше тестировали на Ubuntu 12.04, для Mac OS, измените линии LS к:

"$(ls -lT $file | awk '{ print $8 }')"

Добавьте следующее в ~ / .bashrc:

function react() {
    if [ -z "$1" -o -z "$2" ]; then
        echo "Usage: react <[./]file-to-watch> <[./]action> <to> <take>"
    elif ! [ -r "$1" ]; then
        echo "Can't react to $1, permission denied"
    else
        TARGET="$1"; shift
        ACTION="$@"
        while sleep 1; do
            ATIME=$(stat -c %Z "$TARGET")
            if [[ "$ATIME" != "${LTIME:-}" ]]; then
                LTIME=$ATIME
                $ACTION
            fi
        done
    fi
}

Пример использования inotifywait:

Предположим, я хочу бежать rails test Каждый раз, когда я изменяю соответствующий файл.

1. Сделайте список соответствующих файлов, которые вы хотите посмотреть:

Вы могли бы сделать это вручную, но я нахожу ack Очень полезно сделать этот список.

ack --type-add=rails:ext:rb,erb --rails -f > Inotifyfile

2. Спроси inotifywait сделать работу

while inotifywait --fromfile Inotifyfile; do rails test; done

Вот и все!

ПРИМЕЧАНИЕ. В случае, если вы используете Vagrant для запуска кода на VM, вы можете найти полезные MHALLIN / VAGRANT-NOTION-INVERVER расширение.

ОБНОВИТЬ:Еще лучше, сделай alias и избавиться от файла:

alias rtest="while inotifywait $(ack --type-add=rails:ext:rb,erb --rails -f | tr \\n \ ); do rails test; done"
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top