#!/bin/csh -f # seddiff # ----------------------------------------------------------------------------- # Shell script to make a global change to a set of files via sed, showing # the differences to each file. # ----------------------------------------------------------------------------- # Usage: See Usage section below or run with -h or --help option to see usage. # Assumptions: # - User was write permission on the specified file # - User has write permission on the folder containing the specified file, # in order to create a temp file there. # Effects: # Notes: # Implementation Notes: # Portability Issues: # Revision History: # $Log$ # ----------------------------------------------------------------------------- if ($#argv < 3 || "$1" == "-h" || "$1" == "--help") then echo "Usage: $0:t [options] old_pattern new_pattern filename..." echo " where:" echo " old_pattern = sed pattern to change from" echo " new_pattern = sed pattern to change to" echo " filename = Name of file to edit" echo " options:" echo " -r = Also search current directory recursively" echo " -v = Verbose. More verbose about edited files" echo " -vv = Very verbose. Show name of each file considered" echo " -i = Interactive. Accept/revert each edited file?" echo " -d char = Use char as the delimiter instead of / on the" echo " sed command. Useful when one of the patterns" echo " contains /" echo -n " Examples: -d = -d : -d '?' -d '*' -d \*" echo ' -d "*"' echo " -x pattern = Exclude filenames with this pattern" echo " (Passed to -prune of find command)" echo " -h = Show this help info" echo " --help = Show this help info" echo "Example: $0:t -r -x bin -x classes -d : javalib com/bristle/javalib" exit 1 endif # Collect command line options set recursive_option = "" set verbose_option = "" set very_verbose_option = "" set confirm_option = "" set delimiter_option = "" set delimiter_char = "/" set delimiter_option_and_char = "" set exclude_option = "" set exclude_pattern = "" set find_cmd = "find ." while ($#argv > 0) if ("$1" == "-h" || "$1" == "--help") then shift # If help option was anywhere among the options, call recursively # with just that option, and exit. $0:t --help exit 1 else if ("$1" == "-r") then shift set recursive_option = "-r" else if ("$1" == "-v") then shift # Note: Use the option value itself as the value of verbose_option, # not "true" or something so that we can pass it to this # script for verbose recursive calls. set verbose_option = "-v" else if ("$1" == "-vv") then shift # Note: Use the option value itself as the value of very_verbose_option, # not "true" or something so that we can pass it to this # script for very verbose recursive calls. set very_verbose_option = "-vv" set verbose_option = "-v" else if ("$1" == "-i") then shift # Note: Use the option value itself as the value of confirm_option, # not "true" or something so that we can pass it to this # script for confirming in recursive calls. set confirm_option = "-i" else if ("$1" == "-d") then shift set delimiter_option = "-d" if ("$1" == "") then beep "Option $delimiter_option requires a value" $0:t --help exit 1 else set firstchar = "`set noglob; echo $1:q | cut -c 1`" if ("$firstchar" != "$1") then beep "Option $delimiter_option requires a one-char value" $0:t --help exit 1 else set delimiter_char = "$1" shift set delimiter_option_and_char = "${delimiter_option} ${delimiter_char}" endif endif else if ("$1" == "-x") then shift set exclude_option = "-x" if ("$1" == "") then beep "Option $exclude_option requires a value" $0:t --help exit 1 else set firstchar = "`set noglob ; echo $1:q | cut -c 1`" if ("$firstchar" == "-") then beep "Option $exclude_option requires a value" $0:t --help exit 1 else set exclude_pattern = "$1" set find_cmd = "$find_cmd -name $exclude_pattern -prune -o" shift endif endif else # Not a recognized option. Assume it's the first parameter break endif end if ($#argv < 1) then beep "No old_pattern specified" $0:t --help exit 1 else if ($#argv < 2) then beep "No new_pattern specified" $0:t --help exit 1 else if ($#argv < 3 && "$recursive_option" == "") then beep "No filename specified" $0:t --help exit 1 endif set old_pattern=$1:q shift set new_pattern=$1:q shift set timestamp = `date "+%Y_%m_%d__%H_%M_%S"` set backup=".$0:t_$$_$timestamp" foreach filename ($*:q) if ("$very_verbose_option" != "") then echo -n "Editing ${filename} ... " endif grep "${old_pattern}" ${filename:q} > /dev/null set rc = $status if ($rc == 0) then if ("$very_verbose_option" == "" && "$verbose_option" != "") then echo "Editing ${filename}" endif sed -i ${backup} -e "s${delimiter_char}${old_pattern}${delimiter_char}${new_pattern}${delimiter_char}g" ${filename:q} if ("$very_verbose_option" != "") then echo "EDITED" endif if ("$verbose_option" != "") then echo "Comparing ${filename}${backup} ${filename} ..." endif diff ${filename:q}${backup} ${filename:q} if ("$confirm_option" != "") then set prompt = "Accept or revert these changes (a/r)? " set accept = `promptloop "${prompt}" a r` if ($accept == "a") then rm ${filename:q}${backup} else if ($accept == "r") then beep "Reverting to unedited file." mv ${filename:q}${backup} ${filename:q} endif endif else if ("$very_verbose_option" != "") then echo "no match" endif endif end set find_cmd = "$find_cmd -type f -exec $0 $verbose_option $very_verbose_option $confirm_option $delimiter_option_and_char $old_pattern:q $new_pattern:q {} ;" if ("$recursive_option" != "") then if ("$verbose_option" != "") then echo "Starting recursive search..." echo "$find_cmd" endif set noglob $find_cmd endif