+#! /bin/bash
+
+set -e
+usage () { echo >&2 "$0 FILE ... -- PROG ARGS"; exit 1; }
+case "$#:$1" in
+ 0:* | 1:-h | 1:--help)
+ echo "$0 FILE ... -- PROG ARGS"
+ echo " For each FILE, run PROG ARGS with stdin from FILE. If all is"
+ echo " good, replace each FILE with the corresponding output."
+ echo " Clobbers FILE.old and FILE.new."
+ exit 0
+ ;;
+esac
+declare -a file
+while :; do
+ [ $# -eq 0 ] && usage
+ f=$1; shift
+ [ "$f" = -- ] && break
+ file=("${file[@]}" "$f")
+done
+[ $# -eq 0 ] && usage
+
+cleanup_a () {
+ for f in "${file[@]}"; do
+ rm -f "$f.new" "$f.old"
+ done
+}
+trap cleanup_a EXIT INT QUIT TERM
+
+for f in "${file[@]}"; do "$@" <"$f" >"$f.new"; done
+for f in "${file[@]}"; do cp "$f" "$f.old"; done
+
+cleanup_b () {
+ for f in "${file[@]}"; do
+ rm -f "$f.new"
+ mv "$f.old" "$f"
+ done
+}
+trap cleanup_b EXIT INT QUIT TERM
+
+for f in "${file[@]}"; do mv "$f.new" "$f"; done
+trap '' EXIT INT QUIT TERM
+for f in "${file[@]}"; do rm -f "$f.old"; done
+exit 0