inotifywait fswatch changes macos bash shell

macos - fswatch - linux detect file system changes



Bash script, watch folder, execute command (12)

Estoy tratando de crear un script bash que tome 2 parámetros: un directorio y un comando. Necesito ver este directorio para ver los cambios y cuando algo ha cambiado necesito ejecutar el comando. Soy realmente nuevo en scripts de bash y no estoy realmente seguro de lo que estoy haciendo, así que no me molestes. También estoy en un Mac, no en Linux. Cualquier puntero o recurso externo sería de gran ayuda. Sé que mucha gente lo prueba en Internet y nadie puede hacerlo bien. Realmente estoy tratando de imitar la funcionalidad de reloj de 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



Aquí hay un ejemplo de ver una carpeta de cambios y ejecutar menos compilador cuando se actualiza. Como requisito previo necesita npm y estos el módulo onchange . La comunidad de nodos tiene un montón de diferentes comandos de vigilancia (como onchange). No conozco ninguno que sea compilado binarios independientes.

npm install less onchange -g

Entonces puedes usar algo como:

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

Prefiero un comando BASH sobre la respuesta Grunt que di hace un tiempo.


Aquí hay una plantilla con la que trabajar, comprobará cada 120 segundos los cambios en el directorio pasado y notificará la creación de directorios, archivos o nombres de canalizaciones. Si también desea ejecutar comandos cuando se elimina algo, verifique mi otra respuesta en para obtener ejemplos adicionales de bucle.

#!/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 }

Indique si reemplaza las líneas de echo anteriores con eval <some command> para cada tipo de acción monitoreada, ya que estará más cerca de la automatización de las acciones. Y si desea ver lo que se ve arriba cuando se usa dentro de un script, entonces revise la última versión de script para el proyecto en el que he estado trabajando para la automatización del cifrado y descifrado a través de gpg y tar.


Casi 3 años después y recomendaría esta solución basada en ronco.

Creé un ejemplo de trabajo aquí https://github.com/reggi/watch-execute .

Aquí está el 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''); };


En Mac OS X, puede hacer clic con el botón derecho en una carpeta y luego hacer clic en "Configuración de las acciones de la carpeta". Esto le permitirá adjuntar acciones a una carpeta, es decir, scripts para ejecutar.

OS X viene con una serie de scripts precompilados, o puede crear uno propio.


Escribí una utilidad general llamada watchfile para simplificar este tipo de operaciones.

Es menos poderoso que inotifywatch , pero prefiero una utilidad más simple y menos detallada.

Para la tarea deseada, desea controlar si se han modificado los archivos en el directorio actual. Para enumerar todos los archivos recursivamente en el directorio actual:

find . -type f

Para generar la información de marca de tiempo de cada uno de estos archivos:

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

Ahora, puede monitorear esta salida con la utilidad watchfile y ejecutar un comando CMD cuando esta información cambie:

watchfile -s "find . -type f -print0 | xargs -0 stat" -e CMD


No puedo creer que nadie haya publicado esto todavía.

Primero asegúrese inotify-tools estén instaladas.

Entonces úsalos así:

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

Alternativamente, usar --format lugar de -c en inotifywait sería una idea.

Simplemente el man inotifywait y el man inotifywatch para obtener más información.


Para supervisar de forma continua la carpeta (md5) y ejecutar un comando en el cambio:

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

Funciona en mi sistema operativo X ya que no tengo digest .

En Linux, puede usar md5sum como reemplazo del comando md5 .


Si solo necesita verificar los archivos que se crean / eliminan en el nivel superior (sin consultar las subcarpetas), es posible que desee utilizar lo siguiente.

Utiliza pocos recursos, por lo tanto, puede reaccionar rápidamente, lo uso para buscar un archivo modificado.

#!/bin/bash file="$1" shift tmp=$(mktemp) trap ''rm "$tmp"'' EXIT while true; do while [ ! "$tmp" -ot "$file" ]; do sleep 0.5 done eval "$@ &" echo $! > "$tmp" wait done


probablemente la forma más rápida de hacerlo ... (en 1G git repo, regresa por debajo de 1 segundo)

#!/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


MÉTODO 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 $*

Este script toma dos parámetros [directorio, comando]. Cada 10 segundos, el script ejecuta check() para ver que la carpeta ha cambiado. Si no, duerme y el ciclo se repite.

En el caso de que la carpeta haya cambiado, eval su comando.

MÉTODO 2:
Use un cron para monitorear la carpeta.

Tendrás que instalar incron:

sudo apt-get install incron

Y entonces tu script se verá más o menos así:

#!/bin/bash eval $1

(No será necesario que especifique la carpeta, ya que el trabajo del cron consistirá en supervisar el directorio especificado)

Un ejemplo completo y funcional se puede encontrar aquí:

http://www.errr-online.com/index.php/2011/02/25/monitor-a-directory-or-file-for-changes-on-linux-using-inotify/


#!/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