I am trying to create a bash script with 2 parameters:
I want to watch the
probably the fastest way of doing it.. (on 1G git repo, returns under 1sec.)
#!/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
In Mac OS X, you can just control-click a folder, then click 'Folder Actions Setup'. This will allow you attach actions to a folder, i.e. scripts to run.
OS X comes with a number of prebuilt scripts, or you can create your own.
Here's an example of watching a folder for changes and running a the less compiler when one is updated. As a prereq you need npm and these the module onchange. The node community has a whole bunch of different watch commands (like onchange) I'm not aware of any that are compiled self-contained binaries.
npm install less onchange -g
Then you can use something like:
onchange "./stylesheets/*.less" -- lessc main.less > main.css
I prefer a BASH command over the Grunt answer I gave a while back.
I can’t believe nobody posted this yet.
First make sure inotify-tools
are installed.
Then use them like this:
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
Alternatively, using --format
instead of -c
on inotifywait
would be an idea.
Just man inotifywait
and man inotifywatch
for more infos.
Almost 3 years later and I'd recommend this grunt based solution.
I created a working example here https://github.com/reggi/watch-execute.
Here's the 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');
};
Here's a template to work with, it'll check every 120 seconds for changes in passed directory and notify on creation of directories,files,or names pipes. If you also want to run commands when something is removed then check my other answer on stackoverflow for additional looping examples.
#!/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
}
Hint if you replace the echo
lines above with eval <some command>
for each type of action monitored for you'll be all the closer to automation of actions. And if you wish to see what the above looks like when used within a script then check out the latest script version for the project I've been working on for automation of encryption and decryption via gpg and tar.