#!/usr/bin/env zsh setopt NULL_GLOB print_usage() { name="$(basename "$1")" print "Usage:" print "$name (watch | convert_all | clean) " 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