master-thesis/calca/heat_flow/watch.sh

157 lines
3.9 KiB
Bash

#!/usr/bin/env zsh
setopt NULL_GLOB
print_usage() {
name="$(basename "$1")"
print "Usage:"
print "$name (watch | convert_all | clean) <source_dir> <output_dir>"
print "$name --help"
}
new_path() {
old_path="$1"
rel_path="$(realpath --canonicalize-missing \
--relative-to="$source_dir" "$old_path")"
print "$output_dir/$rel_path"
}
pdf_path() {
xoj_path="$1"
new_path="$(new_path "$xoj_path")"
print "${new_path%.(xoj|xopp)}.pdf"
}
fail_path() {
pdf_path="$1"
print "$pdf_path.fail"
}
convert() {
xoj_path="$1"
pdf_path="$(pdf_path "$xoj_path")"
new_dirpath="$(dirname "$pdf_path")"
fail_path="$(fail_path "$pdf_path")"
print "Converting $xoj_path -> $pdf_path"
# Create the directory if it does not exist
mkdir --verbose --parents "$new_dirpath"
if xournalpp --create-pdf "$pdf_path" "$xoj_path"; then
# Delete a fail notice if it exists
rm --force "$fail_path"
else
# Create a fail notice
print >&2 "Conversion failed. Creating $fail_path"
touch "$fail_path"
fi
}
delete() {
del_path="$1"
del_dirpath="$(dirname "$del_path")"
fail_path="$(fail_path "$del_path")"
print "Deleting $del_path"
rm "$del_path"
# Delete a fail notice if it exists
rm --force "$fail_path"
# Try deleting the directory; only succeeds if it is empty
rmdir --verbose --parents --ignore-fail-on-non-empty "$del_dirpath"
}
watch() {
last_time=""
last_event=""
last_path=""
inotifywait --monitor --recursive \
--event modify --event delete --event move \
--format "%T %e %w%f" \
--timefmt "%s" \
"$source_dir" |
# This works even if the directory or filename contain spaces
while read t event file_path
do
[[ "$t" == "$last_time"
&& "$event" == "$last_event"
&& "$file_path" == "$last_path"
]] && continue
last_time="$t"
last_event="$event"
last_path="$file_path"
[[ "$file_path" == (*.xoj|*.xopp) && "$file_path" != (*autosave*) ]]; is_xoj=$(( !$? ))
[[ -d "$file_path" ]]; is_dir=$(( !$? ))
case "$event" in
MODIFY | MOVED_TO)
(( is_xoj )) && sleep 1s && convert "$file_path";;
DELETE | MOVED_FROM)
if (( is_xoj )); then
pdf_path="$(pdf_path "$file_path")"
[[ -e "$pdf_path" ]] && delete "$pdf_path"
fi;;
MOVED_TO,ISDIR)
convert_all "$file_path"
;;
MOVED_FROM,ISDIR)
rm -r "$(new_path "$file_path")"
;;
*)
print >&2 "Unhandled event: $event $file_path";;
esac
done
}
convert_all() {
subdir="$1"
for xoj_path in "$subdir"/**/*.(xoj|xopp)
do
pdf_path="$(pdf_path "$xoj_path")"
if [[ ! -e "$pdf_path" || "$pdf_path" -ot "$xoj_path" ]]; then
convert "$xoj_path"
fi
done
}
clean() {
subdir="$1"
for pdf_path in "$subdir"/**/*.pdf
do
rel_path="$(realpath --canonicalize-missing \
--relative-to="$output_dir" "$pdf_path")"
xoj_path="$source_dir/${rel_path%.pdf}.xoj"
xopp_path="$source_dir/${rel_path%.pdf}.xopp"
if [[ ! -e "$xoj_path" && ! -e "$xopp_path" ]]; then
print "Neither $xoj_path nor $xopp_path exist."
delete "$pdf_path"
fi
done
}
case "$1" in
--help)
print_usage "$0";;
watch|convert_all|clean)
if (( $# == 3 )); then
source_dir="$2"
output_dir="$3"
else
print_usage "$0" >&2
exit 1
fi
;|
watch)
watch;;
convert_all)
convert_all "$source_dir";;
clean)
clean "$output_dir";;
*)
print_usage "$0" >&2
exit 1;;
esac