#! /bin/bash # Last edited on 2009-10-08 16:39:51 by stolfi #=============================================================== usage="filter-files [-h] ..." # Applies a command to a bunch of files, and compares each # output with the original file. # When the two differ, the is renamed ~~ and the # filter output takes its place. Otherwise the remains # unchanged. # It also lists all changes in the file # /tmp/filter-files-.log. # the -h switch, if present, is passed to diff. #=============================================================== diffopt=( ) if [[ "/$1" == "/-h" ]]; then diffopt=( "$1" ) shift fi cmd=( $1 ); shift log="/tmp/filter-files-$$.log" echo "cmd = [${cmd[@]}]" 1>&2 echo "fixing files..." 1>&2 echo '# File: '${log} > ${log} echo '# Last modified by '$0' on '`date` >> ${log} echo '# ' >> ${log} if [[ $# -gt 10 ]]; then echo '# ' "$0 ${cmd[@]} ${@:0:10}" '...' >> ${log} else echo '# ' "$0 ${cmd[@]} $@" >> ${log} fi echo '# ' >> ${log} echo '# Changes (< = original, > = new): ' >> ${log} echo '# ' >> ${log} for infile in "$@" ; do echo -n "Fixing ${infile} ... " 1>&2 echo ' ' >> ${log} echo -n "Fixing ${infile} ... " >> ${log} if [[ ! ( -f ${infile} ) ]]; then echo "${infile} is not a file\!" 1>&2 continue fi if [[ ! ( -r ${infile} ) ]]; then echo "${infile} is unreadable\!" 1>&2 continue fi backup="${infile}~~" oldbackup="${infile}~~~" result="${infile}~~~~" ${cmd[@]} < ${infile} > ${result} status=$? if [[ ${status} -ne 0 ]]; then /bin/rm ${result} echo "failed, status = ${status}." 1>&2 echo "failed, status = ${status}." >> ${log} break else /usr/bin/cmp -s ${infile} ${result} status=$? if [[ ${status} -eq 0 ]]; then /bin/rm ${result} echo 'no changes.' 1>&2 echo 'no changes.' >> ${log} continue else if [[ -e ${backup} ]]; then /bin/mv -f ${backup} ${oldbackup} fi /bin/mv ${infile} ${backup} /bin/mv ${result} ${infile} chmod --reference=${backup} ${infile} echo 'done.' 1>&2 echo ' changed:' >> ${log} echo ' ' >>${log} /usr/bin/diff ${diffopt} ${backup} ${infile} \ | sed \ -e '/^---/d' \ -e '1,$s/^[0-9].*//g' \ >> ${log} fi fi done echo "Done (see ${log})." 1>&2