Сценарий Bash, просмотр папки, выполнение команды - PullRequest
35 голосов
/ 25 июня 2011

Я пытаюсь создать bash-скрипт, который принимает 2 параметра: каталог и команду.Мне нужно следить за этим каталогом на предмет изменений, и когда что-то изменилось, мне нужно выполнить команду.Я действительно новичок в bash-скриптинге и не совсем уверен в том, что делаю, так что будьте спокойны со мной.Я также на Mac, а не Linux.Любые указатели или внешние ресурсы очень помогли бы.Я знаю, что многие люди пробуют это в Интернете, и никто не может сделать это правильно.Я действительно пытаюсь имитировать функциональность часов SASS.

#!/bin/bash

#./watch.sh $PATH $COMMAND

DIR=$1  

ls -l $DIR > $DIR/.begin
#this does not work
DIFFERENCE=$(diff .begin .end)

if [ $DIFFERENCE = '\n']; then
    #files are same
else
    $2
fi 

ls -l $DIR > $DIR/.end

Ответы [ 12 ]

37 голосов
/ 27 февраля 2012

Для непрерывного рекурсивного мониторинга папки (md5) и выполнения команды при изменении:

daemon() {
    chsum1=""

    while [[ true ]]
    do
        chsum2=`find src/ -type f -exec md5 {} \;`
        if [[ $chsum1 != $chsum2 ]] ; then           
            compile
            chsum1=$chsum2
        fi
        sleep 2
    done
}

Работает на моей OS X, поскольку у меня нет digest.

В Linux вы можете использовать md5sum вместо команды md5.

10 голосов
/ 08 января 2015

Вот пример просмотра папки на предмет изменений и запуска менее компилятора при его обновлении. В качестве предварительного условия вам необходимо npm, и это модуль onchange . В сообществе узлов есть целая куча различных команд наблюдения (например, onchange). Я не знаю ни одной, которая бы компилировала автономные двоичные файлы.

npm install less onchange -g

Тогда вы можете использовать что-то вроде:

onchange "./stylesheets/*.less" -- lessc main.less > main.css

Я предпочитаю команду BASH, а не Ворчливый ответ Я дал некоторое время назад.

10 голосов
/ 07 июля 2012

Не могу поверить, что никто еще не опубликовал это.

Сначала убедитесь, что установлены inotify-tools.

Затем используйте их следующим образом:

logOfChanges="/tmp/changes.log.csv" # Set your file name here.

# Lock and load
inotifywait -mrcq $DIR > "$logOfChanges" &
IN_PID=$$

# Do your stuff here
...

# Kill and analyze
kill $IN_PID
cat "$logOfChanges" | while read entry; do
   # Split your CSV, but beware that file names may contain spaces too.
   # Just look up how to parse CSV with bash. :)
   path=... 
   event=...
   ...  # Other stuff like time stamps?
   # Depending on the event…
   case "$event" in
     SOME_EVENT) myHandlingCode path ;;
     ...
     *) myDefaultHandlingCode path ;;
done

В качестве альтернативы можно было бы использовать --format вместо -c на inotifywait.

Просто man inotifywait и man inotifywatch для получения дополнительной информации.

10 голосов
/ 25 июня 2011

МЕТОД 1:

#!/bin/sh

check() {
    dir="$1"
    chsum1=`digest -a md5 $dir | awk '{print $1}'`
    chsum2=$chsum1

    while [ $chsum1 -eq $chsum2 ]
    do
        sleep 10
        chsum2=`digest -a md5 $dir | awk '{print $1}'`
    done

    eval $2
}

check $*

Этот сценарий принимает два параметра [каталог, команда].Каждые 10 секунд скрипт выполняет check(), чтобы увидеть, что папка изменилась.Если он не спит, и цикл повторяется.

В случае, если папка изменилась, eval ваша команда.

МЕТОД 2:
Используйте cron для мониторинга папки.

Вам нужно будет установить incron:

 sudo apt-get install incron

И тогда ваш скрипт будет выглядеть примерно так:

#!/bin/bash
eval $1

(вам не нужно указывать папку, так как cron будет следить за указанным каталогом)

Полный рабочий пример можно найти здесь:

http://www.errr -online.com / index.php / 2011/02/25 / монитор-а-каталог или-файлов для-изменений-на-Linux-используя-Inotify /

5 голосов
/ 17 июля 2014

, вероятно, самый быстрый способ сделать это .. (в 1G git repo возвращается менее 1 секунды)

#!/bin/bash

watch() {

    echo watching folder $1/ every $2 secs.

while [[ true ]]
do
    files=`find $1 -type f -mtime -$2s`
    if [[ $files == "" ]] ; then
        echo "nothing changed"
    else
            echo changed, $files
    fi
    sleep $2
done
}

watch folder 3
3 голосов
/ 09 января 2012

В Mac OS X вы можете просто щелкнуть по папке, удерживая клавишу Control, затем нажать «Настройка действий с папками». Это позволит вам прикреплять действия к папке, т.е. запускать сценарии.

OS X поставляется с несколькими встроенными сценариями, или вы можете создать свой собственный.

1 голос
/ 16 февраля 2016
#!/bin/bash

# Author: Devonte
# NGINX WATCH DAEMON
# Place file in root of nginx folder /etc/nginx
# This will test your nginx config on any change and
# if there are no problems it will reload your configuration
# USAGE: sh nginx-watch.sh

dir=`dirname $0`

checksum_initial=`tar -cf - $dir | md5sum | awk '{print $1}'`
checksum_now=$checksum_initial

# Start nginx
nginx

while true
do
    sleep 3
    checksum_now=`tar -cf - $dir | md5sum | awk '{print $1}'`

    if [ $checksum_initial != $checksum_now ]; then
        echo "[ NGINX ] A configuration file changed. Reloading..."
        nginx -t && nginx -s reload;
    fi

    checksum_initial=$checksum_now
done
1 голос
/ 20 августа 2014

Я написал общую утилиту под названием watchfile для упрощения операций такого типа.

Она менее мощная, чем inotifywatch, но я предпочитаю более простую, менее многословную утилиту.

Для желаемой задачи вы хотите отслеживать, были ли изменены какие-либо файлы в текущем каталоге.Чтобы рекурсивно вывести список всех файлов в текущем каталоге:

find . -type f

Чтобы вывести информацию о метках времени каждого из этих файлов:

find . -type f -print0 | xargs -0 stat

Теперь вы можете отслеживать этот вывод с помощью watchfile утилита и выполнить команду CMD когда эта информация изменится:

watchfile -s "find . -type f -print0 | xargs -0 stat" -e CMD
1 голос
/ 19 марта 2014

Спустя почти 3 года, и я бы порекомендовал это решение на основе хруста.

Я создал рабочий пример здесь https://github.com/reggi/watch-execute.

Вот Gruntfile.js:

module.exports = function (grunt) {
  grunt.initConfig({
    shell: {
      run_file:{
        command: 'sh ./bash.sh',
        options: {
            stdout: true
        }
      }
    },
    watch: {
      run_file: {
        files: ["./watchme/*"],
        tasks: ["shell:run_file"]
      }
    }
  });
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-shell');
};
0 голосов
/ 26 ноября 2016

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

#!/usr/bin/env bash
Var_dir="${1:-/tmp}"
Var_diff_sleep="${2:-120}"
Var_diff_opts="--suppress-common-lines"
Func_parse_diff(){
    _added="$(grep -E '>' <<<"${@}")"
    if [ "${#_added}" != "0" ]; then
        mapfile -t _added_list <<<"${_added//> /}"
        _let _index=0
        until [ "${#_added_list[@]}" = "${_index}" ]; do
            _path_to_check="${Var_dir}/${_added_list[${_index}]}"
            if [ -f "${_path_to_check}" ]; then
                echo "# File: ${_path_to_check}"
            elif [ -d "${_path_to_check}" ]; then
                echo "# Directory: ${_path_to_check}"
            if [ -p "${_path_to_check}" ]; then
                echo "# Pipe: ${_path_to_check}"
            fi
            let _index++
        done
        unset _index
    fi
}
Func_watch_bulk_dir(){
    _current_listing=""
    while [ -d "${Var_dir}" ]; do
        _new_listing="$(ls "${Var_dir}")"
        _diff_listing="$(diff ${Var_dec_diff_opts} <(${Var_echo} "${_current_listing}") <(${Var_echo} "${_new_listing}"))"
        if [ "${_diff_listing}" != "0" ]; then
            Func_parse_diff "${_diff_listing}"
        fi
        _current_listing="${_new_listing}"
        sleep ${Var_diff_sleep}
    done
}

Подсказка, если вы замените строки echo выше на eval <some command> для каждого отслеживаемого типа действия, вы будете ближе к автоматизации действий.И если вы хотите увидеть, как это выглядит при использовании в скрипте, то ознакомьтесь с последней версией скрипта для проекта, над которым я работал для автоматизации шифрования и дешифрования с помощью gpg и tar.

...