This repository has been archived on 2024-03-28. You can view files and clone it, but cannot push or open issues or pull requests.
dotfiles/common/bin/fsw

98 lines
2.9 KiB
Plaintext
Raw Permalink Normal View History

2018-11-08 07:32:36 -06:00
#!/usr/bin/env bash
2019-10-30 17:57:30 -05:00
_VERSION="0.2.0"
function help() {
I=" "
2020-02-13 11:14:03 -06:00
cat << USAGE
fsw - run a command when a file is modified - v$_VERSION
2019-10-30 17:57:30 -05:00
Usage:
${I}fsw <command> [filter] [dirs...]
${I}command - the specified bash command to eval
${I}filter - an optional filename filter
${I}dirs - the directories to watch (defaults to current directory)
Advanced:
${I}Command Variables:
${I}${I}Your commands have runtime access to some variables associated with the
${I}${I}${I}inotifywait event enabling further extensibility:
${I}${I}+ FSW_FILENAME - the name of the file
${I}${I}+ FSW_DIR - the directory containing the file
${I}${I}+ FSW_PATH - the full relative path of the file
${I}${I}+ FSW_FILE_EVENTS - a comma-separated list of the inotify events
${I}Environment:
${I}${I}Some customization options exist using environment variables
${I}${I}${I}due to their uncommon usage.
${I}${I}+ FSW_EVENTS - the list of events to have inotifywait observe
2019-11-17 09:06:44 -06:00
2019-10-30 17:57:30 -05:00
References:
${I}+ Filter works with grep -P
${I}+ See inotifywait(1) for FSW_EVENTS options.
2019-11-17 09:06:44 -06:00
2019-10-30 17:57:30 -05:00
Examples:
${I}fsw 'make' '\.c$'
${I}fsw 'bash \$filename' '\.bash$'
${I}fsw 'mix test --failed' '.exs?$' lib test
${I}FSW_EVENTS=open,access fsw 'espeak "Intruder Alert!"' \\
${I}${I}${I}'.*' /etc/secrets \$HOME/.secrets
USAGE
}
2019-12-12 11:02:24 -06:00
dbg() {
2020-02-13 11:14:03 -06:00
if [[ -n ${FSW_DEBUG+x} ]]; then
echo -e "[debug] fsw: $*"
2019-12-12 11:02:24 -06:00
fi
}
2020-02-13 11:14:03 -06:00
contains_element () {
local e match="$1"; shift
for e; do [[ "$e" == "$match" ]] && return 0; done
return 1
}
2019-10-30 17:57:30 -05:00
if [[ $1 = '-h' ]] || [[ $1 = '--help' ]] || [[ -z $1 ]]; then
help
exit 0
fi
FSW_EVENTS="${FSW_EVENTS:-close_write}"
2019-12-12 11:02:24 -06:00
dbg "Events: $FSW_EVENTS"
2019-10-30 17:57:30 -05:00
SHELL_COMMAND="${1}"; shift
2019-12-12 11:02:24 -06:00
dbg "Command: $SHELL_COMMAND"
2019-10-30 17:57:30 -05:00
FILTER="${1}"; shift
2019-12-12 11:02:24 -06:00
dbg "Filter: $FILTER"
dbg "Directory: ${1}"
2019-10-30 17:57:30 -05:00
DIRS=("${1:-.}"); shift
2019-11-12 16:39:31 -06:00
if [[ -e $FILTER ]]; then
# TODO: this is a sad hack/workaround
echo "It looks like your filter is an actual file. I'll just watch that for you."
DIRS=("${FILTER}")
fi
2020-02-13 11:14:03 -06:00
while [[ -n $1 ]] && realpath "$1" &> /dev/null; do
2019-12-12 11:02:24 -06:00
dbg "Directory: ${1}"
2019-10-30 17:57:30 -05:00
DIRS+=("$1"); shift
done
2020-02-13 11:14:03 -06:00
inotifywait -m -e "${FSW_EVENTS},delete,delete_self" -r "${DIRS[@]}" 2>&1 \
2019-10-30 17:57:30 -05:00
| grep --line-buffered -v ' Beware: since -r was given, this may take a while!' \
| while read -r dir events filename; do
2020-02-13 11:14:03 -06:00
if contains_element "$dir" "${DIRS[@]}" && [[ $events =~ "delete" ]]; then
echo "One of the watched directories (\"$dir\") was deleted. Exiting..."
exit 75
fi
2019-10-30 17:57:30 -05:00
if [[ "$dir $events" = "Watches established." ]]; then
echo "Ready."
2020-02-13 11:14:03 -06:00
dbg "Directory: ${DIRS[*]}"
2019-10-30 17:57:30 -05:00
else
export FSW_FILENAME="$filename"
export FSW_DIR="$dir"
export FSW_PATH="$dir$filename"
export FSW_FILE_EVENTS="$events"
2019-11-17 09:06:44 -06:00
export FSW_EVENT="$events $dir$filename"
2019-12-12 11:02:24 -06:00
dbg "Event:\n $(date)\n $FSW_PATH\n $FILTER\n $FSW_EVENT\n $dir $events $filename\n ${SHELL_COMMAND}"
dbg "Filtered Event: $(<<< "$FSW_PATH" grep -P "$FILTER")"
2019-12-12 13:31:18 -06:00
<<< "$FSW_PATH" grep -P "$FILTER" > /dev/null 2>&1 && eval "${SHELL_COMMAND}"
2019-10-30 17:57:30 -05:00
fi
2018-11-08 07:32:36 -06:00
done