diff options
Diffstat (limited to 'examples/scripts.v2/ren')
-rw-r--r-- | examples/scripts.v2/ren | 585 |
1 files changed, 0 insertions, 585 deletions
diff --git a/examples/scripts.v2/ren b/examples/scripts.v2/ren deleted file mode 100644 index da760264..00000000 --- a/examples/scripts.v2/ren +++ /dev/null @@ -1,585 +0,0 @@ -#!/bin/bash -#@ This program came from: ftp://ftp.armory.com/pub/scripts/ren -#@ Look there for the latest version. -#@ If you don't find it, look through http://www.armory.com/~ftp/ -# -# @(#) ren 2.1.1 2002-03-17 -# 1990-06-01 John H. DuBois III (john@armory.com) -# 1991-02-25 Improved help info -# 1992-06-07 Remove quotes from around shell pattern as required by new ksh -# 1994-05-10 Exit if no globbing chars given. -# 1995-01-23 Allow filename set to be given on command line. -# 1997-09-24 1.4 Let [] be used for globbing. Added x option. -# 1997-11-26 1.4.1 Notice if the sequences of globbing chars aren't the same. -# 1999-05-13 Changed name to ren to avoid conflict with /etc/rename -# 2000-01-01 1.4.2 Let input patterns that contain whitespace be used. -# 2001-02-14 1.5 Better test for whether old & new globbing seqs are identical. -# 2001-02-20 1.6 Added pP options. -# 2001-02-27 1.7 Added qf options. Improved interpretation of rename patterns. -# 2001-05-10 1.8 Allow multiple pP options. Added Qr options. -# 2001-07-25 2.0 Added mz options. -# 2001-11-25 2.1 Allow segment ranges to be given with -m. Work under ksh93. -# 2002-03-17 2.1.1 Fixed bug in test for legal expressions. - -# todo: It would be nice to be able to escape metacharacters with '\' -# todo: Should enhance patterns to make ] in a pair of brackets work ([]]) -# todo: Allow use of all ksh globbing patterns. -# todo: Allow use of extended regexps, with () to enumerate pieces and \num to -# todo: select them. -# -# Modifications for bash made by Chet Ramey <chet@po.cwru.edu> - -name=${0##*/} -Usage="Usage: -$name [-fhqtv] [-m<segstart[:segend]=operation>] [-z<len>] [-[pP]<pattern>] - oldpattern [newpattern [filename ...]] -or -$name -r [same options as above] oldpattern newpattern directory ..." -tell=false -verbose=false -warn=true -warnNoFiles=true -debug=false -recurse=false -inclPat= -exclPat= -declare -i inclCt=0 exclCt=0 -check=true -declare -i j op_end_seg - -# Begin bash additions -shopt -s extglob - -# -# ksh print emulation -# -# print [-Rnprsu[n]] [-f format] [arg ...] -# -# - end of options -# -R BSD-style -- only accept -n, no escapes -# -n do not add trailing newline -# -p no-op (no coprocesses) -# -r no escapes -# -s print to the history file -# -u n redirect output to fd n -# -f format printf "$format" "$@" -# - -print() -{ - local eflag=-e - local nflag= fflag= c - local fd=1 - - OPTIND=1 - while getopts "fRnprsu:" c - do - case $c in - R) eflag= ;; - r) eflag= ;; - n) nflag=-n ;; - s) sflag=y ;; - f) fflag=y ;; - u) fd=$OPTARG ;; - p) ;; - esac - done - shift $(( $OPTIND - 1 )) - - if [ -n "$fflag" ]; then - builtin printf "$@" >&$fd - return - fi - - case "$sflag" in - y) builtin history -s "$*" ;; - *) builtin echo $eflag $nflag "$@" >&$fd - esac -} - -# End bash additions - -while getopts :htvxp:P:fqQrm:z: opt; do - case $opt in - h) - print -r -- \ -"$name: rename files by changing parts of filenames that match a pattern. -$Usage -oldpattern and newpattern are subsets of sh filename patterns; the only -globbing operators (wildcards) allowed are ?, *, and []. All filenames that -match oldpattern will be renamed with the filename characters that match the -constant (non-globbing) characters of oldpattern changed to the corresponding -constant characters of newpattern. The characters of the filename that match -the globbing operators of oldpattern will be preserved. Globbing operators -in oldpattern must occur in the same order in newpattern; for every globbing -operators in newpattern there must be an identical globbing operators in -oldpattern in the same sequence. Both arguments should be quoted since -globbing operators are special to the shell. If filenames are given, only -those named are acted on; if not, all filenames that match oldpattern are acted -on. newpattern is required in all cases except when -m is given and no further -arguments are given. -If you are unsure whether a $name command will do what you intend, issue it -with the -t option first to be sure. -Examples: -$name \"/tmp/foo*.ba.?\" \"/tmp/new*x?\" - All filenames in /tmp that match foo*.ba.? will have the \"foo\" part - replaced by \"new\" and the \".ba.\" part replaced by \"x\". - For example, /tmp/fooblah.ba.baz would be renamed to /tmp/newblahxbaz. -$name \* \*- foo bar baz - foo, bar, and baz will be renamed to foo-, bar-, and baz-. -$name '????????' '????-??-??' - All filenames that are 8 characters long will be changed such that dashes - are inserted after the 4th and 6th characters. -Options: --h: Print this help. --r: Recursive operation. Filenames given on the command line after oldpattern - and newpattern are taken to be directories to traverse recursively. For - each subdirectory found, the specified renaming is applied to any matching - filenames. oldpattern and newpattern should not include any directory - components. --p<pattern>, -P<pattern>: Act only on filenames that do (if -p is given) or do - not (if -P is given) match the sh-style filename globbing pattern - <pattern>. This further restricts the filenames that are acted on, beyond - the filename selection produced by oldpattern and the filename list (if - any). <pattern> must be quoted to prevent it from being interpreted by the - shell. Multiple instances of these options may be given. In this case, - filenames are acted on only if they match at least one of the patterns - given with -p and do not match any of the patterns given with -P. --m<segstart[:segend]=operation>: For each file being renamed, perform a - mathematical operation on the string that results from concatenating - together the filename segments that matched globbing operator numbers - segstart through segend, where operators are numbered in order of - occurrence from the left. For example, in the pattern a?b*c[0-9]f, segment - 1 consists of the character that matched ?, segment 2 consists of the - character(s) that matched *, and segment 3 consists of the character that - matched [0-9]. The selected segments are replaced with the result of the - mathematical operation. - The concatenated string must consist of characters that can be interpreted - as a decimal integer; if it does not, the filename is not acted on. This - number is assigned to the variable 'i', which can be referenced by the - operation. The operations available are those understood by the ksh - interpreter, which includes most of the operators and syntax of the C - language. The original filename segment is replaced by the result of the - operation. If -m is used, newpattern may be an empty string or not given - at all (if no directory/file names are given). In this case, it is taken - to be the same as oldpattern. - If segend is given, any fixed text that occurs in the pattern between the - starting and ending globbing segments is discarded. If there are fewer - globbing segments than segend, no complaint is issued; the string is formed - from segment segstart through the last segment that does exist. - If segend is not given, the only segment acted on is startseg. - Examples: - $name -m3=i+6 '??*.ppm' - This is equivalent to: - $name -m3=i+6 '??*.ppm' '??*.ppm' - Since the old pattern and new pattern are identical, this would - normally be a no-op. But in this case, if a filename of ab079.ppm is - given, it is changed to ab85.ppm. - $name '-m1:2=i*2' 'foo??bar' - This will change a file named foo12bar to foo24bar - $name '-m1:2=i*2' 'foo?xyz?bar' - This will also change a file named foo1xyz2bar to foo24bar --z<len>: Set the size of the number fields that result when -m is used. The - field is truncated to the trailing <len> digits or filled out to <len> - digits with leading zeroes. In the above example, if -z3 is given, the - output filename will be ab085.ppm. --f: Force rename. By default, $name will not rename files if a file with the - new filename already exists. If -f is given, $name will carry out the - rename anyway. --q: Quiet operation. By default, if -f is given, $name will still notify the - user if a rename results in replacement of an already-existing filename. - If -q is given, no notification is issued. --Q: Suppress other warnings. By default, a warning is issued if no files are - selected for acting upon. If -Q is given, no warning is issued. --v: Show the rename commands being executed. --t: Show what rename commands would be done, but do not carry them out." - exit 0 - ;; - f) - check=false - ;; - q) - warn=false - ;; - Q) - warnNoFiles=false - ;; - r) - warnNoFiles=false - recurse=true - ;; - t) - tell=true - ;; - v) - verbose=true - ;; - x) - verbose=true - debug=true - ;; - p) - inclPats[inclCt]=$OPTARG - ((inclCt+=1)) - ;; - P) - exclPats[exclCt]=$OPTARG - ((exclCt+=1)) - ;; - m) - # Store operation for each segment number in ops[num] - # Store ending segment number in op_end_seg[num] - range=${OPTARG%%=*} - op=${OPTARG#*=} - start=${range%%:*} - end=${range#*:} - if [[ "$start" != +([0-9]) || "$start" -eq 0 ]]; then - print -ru2 -- "$name: Bad starting segment number given with -m: $start" - exit 1 - fi - if [[ "$end" != +([0-9]) || "$end" -eq 0 ]]; then - print -ru2 -- "$name: Bad ending segment number given with -m: $end" - exit 1 - fi - if [[ start -gt end ]]; then - print -ru2 -- "$name: Ending segment ($end) is less than starting segment ($start)" - exit 1 - fi - if [[ "$op" != @(|*[!_a-zA-Z0-9])i@(|[!_a-zA-Z0-9]*) ]]; then - print -ru2 -- \ - "$name: Operation given with -m does not reference 'i': $op" - exit 1 - fi - # Test whether operation is legal. let returns 1 both for error - # indication and when last expression evaluates to 0, so evaluate 1 - # after test expression. - i=1 - let "$op" 1 2>/dev/null || { - print -ru2 -- \ - "$name: Bad operation given with -m: $op" - exit 1 - } - ops[start]=$op - op_end_seg[start]=$end - ;; - z) - if [[ "$OPTARG" != +([0-9]) || "$OPTARG" -eq 0 ]]; then - print -ru2 -- "$name: Bad length given with -z: $OPTARG" - exit 1 - fi - typeset -Z$OPTARG j || exit 1 - ;; - +?) # no way to tell getopts to not treat +x as an option - print -r -u2 "$name: Do not prefix options with '+'." - exit 1 - ;; - :) - print -r -u2 \ -"$name: Option -$OPTARG requires a value. -$Usage -Use -h for help." - exit 1 - ;; - \?) - print -r -u2 \ -"$name: -$OPTARG: no such option. -$Usage -Use -h for help." - exit 1 - ;; - esac -done - -# remove args that were options -let OPTIND=OPTIND-1 -shift $OPTIND - -oldpat=$1 -newpat=$2 - -# If -m is given, a non-existant or null newpat should be set to oldpat -if [ ${#ops[*]} -gt 0 ]; then - case $# in - 0) - ;; - 1) - set -- "$oldpat" "$oldpat" - newpat=$oldpat - $debug && print -ru2 -- "Set new pattern to: $newpat" - ;; - *) - if [ -z "$newpat" ]; then - shift 2 - set -- "$oldpat" "$oldpat" "$@" - newpat=$oldpat - $debug && print -ru2 -- "Set new pattern to: $newpat" - fi - ;; - esac -fi - -# Make sure input patterns that contain whitespace can be expanded properly -IFS= - -origPat=$oldpat - -# Generate list of filenames to act on. -case $# in -[01]) - print -u2 "$Usage\nUse -h for help." - exit 1 - ;; -2) - if $recurse; then - print -r -u2 "$name: No directory names given with -r. Use -h for help." - exit 1 - fi - set -- $oldpat # Get list of all filenames that match 1st globbing pattern. - if [[ ! -a $1 ]]; then - $warnNoFiles && print -r -- "$name: No filenames match this pattern: $oldpat" - exit - fi - ;; -*) - shift 2 - ;; -esac - -integer patSegNum=1 numPatSegs - -# For old ksh -# while [[ "$oldpat" = *'[\*\?]'* ]]; do - -# Example oldpat: foo*.a -# Example newpat: bar*.b - -# Build list of non-pattern segments and globbing segments found in arguments. -# Note the patterns given are used to get the list of filenames to act on, -# to delimit constant segments, and to determine which parts of filenames are -# to be replaced. -# Examples given for first iteration (in the example, the only iteration) -# The || newpat is to ensure that new pattern does not have more globbing -# segments than old pattern -while [[ "$oldpat" = *@([\*\?]|\[+([!\]])\])* || - "$newpat" = *@([\*\?]|\[+([!\]])\])* ]]; do - ## Get leftmost globbing pattern in oldpat - - # Make r be oldpat with smallest left piece that includes a globbing - # pattern removed from it - r=${oldpat#*@([\*\?]|\[+([!\]])\])} # r=.a - # Make pat be oldpat with the above removed from it, leaving smallest - # left piece that includes a globbing pattern - pat=${oldpat%%"$r"} # pat=foo* - # Make l be pat with the globbing pattern removed from the right, - # leaving a constant string - l=${pat%@([\*\?]|\[+([!\]])\])} # l=foo - # Remove the constant part of pat from the left, leaving the globbing - # pattern - pat=${pat#"$l"} # pat=* - - # Do the same thing for newpat, solely to provide a reliable test that - # both oldpat & newpat contain exactly the same sequence of globbing - # patterns. - r=${newpat#*@([\*\?]|\[+([!\]])\])} # r=.b - npat=${newpat%%"$r"} # pat=bar* - l=${npat%@([\*\?]|\[+([!\]])\])} # l=bar - npat=${npat#"$l"} # npat=* - - if [[ "$pat" != "$npat" ]]; then - print -ru2 -- \ -"$name: Old-pattern and new-pattern do not have the same sequence of globbing chars. -Pattern segment $patSegNum: Old pattern: $pat New pattern: $npat" - exit 1 - fi - - ## Find parts before & after pattern - # oldpre[] stores the old constant part before the pattern, - # so that it can be removed and replaced with the new constant part. - oldpre[patSegNum]=${oldpat%%"$pat"*} # oldpre[1]=foo - # oldsuf stores the part that follows the globbing pattern, - # so that it too can be removed. - # After oldpre[] & oldsuf[] have been removed from a filename, what remains - # is the part matched by the globbing pattern, which is to be retained. - oldsuf[patSegNum]=${oldpat#*"$pat"} # oldsuf[1]=.a - # newpre[] stores the new constant part before the pattern, - # so that it can be used to replace the old constant part. - newpre[patSegNum]=${newpat%%"$pat"*} # newpre[1]=bar - # Get rid of processed part of patterns - oldpat=${oldpat#${oldpre[patSegNum]}"$pat"} # oldpat=.a - newpat=${newpat#${newpre[patSegNum]}"$pat"} # newpat=.b - # Store either * or ? in pats[], depending on whether this segment matches 1 - # or any number of characters. - [[ "$pat" = \[* ]] && pat=? - pats[patSegNum]=$pat - ((patSegNum+=1)) -done - -if [ patSegNum -eq 1 ]; then - print -u2 "No globbing chars in pattern." - exit 1 -fi - -oldpre[patSegNum]=${oldpat%%"$pat"*} # oldpre[2]=.a -oldsuf[patSegNum]=${oldpat#*"$pat"} # oldsuf[2]=.a -newpre[patSegNum]=${newpat%%"$pat"*} # newpre[2]=.b - -numPatSegs=patSegNum - -if $debug; then - patSegNum=1 - while [[ patSegNum -le numPatSegs ]]; do - print -ru2 -- \ -"Old prefix: <${oldpre[patSegNum]}> Old suffix: <${oldsuf[patSegNum]}> New prefix: <${newpre[patSegNum]}> Pattern: <${pats[patSegNum]}>" - ((patSegNum+=1)) - done -fi - -# Example filename: foox.a -# Example oldpat: foo*.a -# Example newpat: bar*.b - -integer numFiles=0 - -# Usage: renameFile filename [dirname] -# [dirname] is a directory name to prefix filenames with when they are printed -# for informational purposes. -# Uses globals: -# inclCt exclCt inclPats[] exclPats[] ops[] -# numPatSegs oldpre[] oldsuf[] newpre[] pats[] -# check warn tell verbose name -# Modifies globals: numFiles -function renameFile { - typeset file=$1 subdir=$2 - integer patSegNum patnum - typeset origname porigname newfile matchtext pnewfile matchsegs - integer startseg endseg - - origname=$file # origname=foox.a - porigname=$subdir$file - # Unfortunately, ksh88 does not do a good job of allowing for patterns - # stored in variables. Without the conditional expression being eval'ed, - # only sh patterns are recognized. If the expression is eval'ed, full - # ksh expressions can be used, but then expressions that contain whitespace - # break unless the user passed a pattern with the whitespace properly - # quoted, which is not intuititive. This is fixed in ksh93; full patterns - # work without being eval'ed. - if [ inclCt -gt 0 ]; then - patnum=0 - while [ patnum -lt inclCt ]; do - [[ "$file" = ${inclPats[patnum]} ]] && break - ((patnum+=1)) - done - if [ patnum -eq inclCt ]; then - $debug && print -ru2 -- "Skipping not-included filename '$porigname'" - return 1 - fi - fi - patnum=0 - while [ patnum -lt exclCt ]; do - if [[ "$file" = ${exclPats[patnum]} ]]; then - $debug && print -ru2 -- "Skipping excluded filename '$porigname'" - return 1 - fi - ((patnum+=1)) - done - # Extract matching segments from filename - ((numFiles+=1)) - patSegNum=1 - while [[ patSegNum -le numPatSegs ]]; do - # Remove a fixed prefix iteration: 1 2 - file=${file#${oldpre[patSegNum]}} # file=x.a file= - # Save the part of this suffix that is to be retained. To do this, we - # need to know what part of the suffix matched the current globbing - # segment. If the globbing segment is a *, this is done by removing - # the minimum part of the suffix that matches oldsuf (since * matches - # the longest segment possible). If the globbing segment is ? or [] - # (the latter has already been coverted to ?), it is done by taking the - # next character. - if [ "${pats[patSegNum]}" == \? ]; then - matchtext=${file#?} - matchtext=${file%$matchtext} - else - matchtext=${file%${oldsuf[patSegNum]}} # matchtext=x matchtext= - fi - $debug && print -ru2 -- "Matching segment $patSegNum: $matchtext" - file=${file#$matchtext} # file=.a file=.a - - matchsegs[patSegNum]=$matchtext - ((patSegNum+=1)) - done - - # Paste fixed and matching segments together to form new filename. - patSegNum=0 - newfile= - while [[ patSegNum -le numPatSegs ]]; do - matchtext=${matchsegs[patSegNum]} - startseg=patSegNum - if [ -n "${ops[startseg]}" ]; then - endseg=${op_end_seg[startseg]} - while [ patSegNum -lt endseg ]; do - ((patSegNum+=1)) - matchtext=$matchtext${matchsegs[patSegNum]} - done - if [[ "$matchtext" != +([-0-9]) ]]; then - print -ru2 -- \ -"Segment(s) $startseg - $endseg ($matchtext) of file '$porigname' do not form an integer; skipping this file." - return 2 - fi - i=$matchtext - let "j=${ops[startseg]}" || { - print -ru2 -- \ -"Operation failed on segment(s) $startseg - $endseg ($matchtext) of file '$file'; skipping this file." - return 2 - } - $debug && print -ru2 -- "Converted $matchtext to $j" - matchtext=$j - fi - newfile=$newfile${newpre[startseg]}$matchtext # newfile=barx newfile=barx.b - ((patSegNum+=1)) - done - - pnewfile=$subdir$newfile - if $check && [ -e "$newfile" ]; then - $warn && - print -ru2 -- "$name: Not renaming \"$porigname\"; destination filename \"$pnewfile\" already exists." - return 2 - fi - if $tell; then - print -n -r -- "Would move: $porigname -> $pnewfile" - $warn && [ -e "$newfile" ] && print -n -r " (destination filename already exists; would replace it)" - print "" - else - if $verbose; then - print -n -r -- "Moving: $porigname -> $pnewfile" - $warn && [ -e "$newfile" ] && print -n -r -- " (replacing old destination filename \"$pnewfile\")" - print "" - elif $warn && [ -e "$newfile" ]; then - print -r -- "$name: Note: Replacing old file \"$pnewfile\"" - fi - mv -f -- "$origname" "$newfile" - fi -} - -if $recurse; then - oPWD=$PWD - find "$@" -depth -type d ! -name '* -*' -print | while read dir; do - cd -- "$oPWD" - if cd -- "$dir"; then - for file in $origPat; do - renameFile "$file" "$dir/" - done - else - print -ru2 -- "$name: Could not access directory '$dir' - skipped." - fi - done -else - for file; do - renameFile "$file" - done -fi - -if [ numFiles -eq 0 ]; then - $warnNoFiles && print -ru2 -- \ - "$name: All filenames were excluded by patterns given with -p or -P." -fi |