#!/bin/bash ## webmv -- rename or move one file in a "web" directory -- by Eugene Reimer 2001-Oct; ## USAGE: see the HELP-output below; AT="$@" while [ $# -gt 0 ] && [[ $1 == -* ]];do ##parse the options case "$1" in -f|--for*) FORCE=1 ;; -k|--kee*) CHGARG="$CHGARG -k" ;; -n|--nob*) CHGARG="$CHGARG -n" ;; -T|--tmp*) CHGARG="$CHGARG -T" ;; -R|--nor*) NOREDIRECT=1 ;; ##2009-03-21: new -S|--nos*) NOSRC=1 ;; ##2009-03-21: new -q|--qui*) CHGARG="$CHGARG -q"; QUIET=1 ;; -t|--tes*) CHGARG="$CHGARG -t"; TEST=1; PROMPT= ;; -p|--pro*) CHGARG="$CHGARG -p"; PROMPT=1; TEST= ;; -\?|--hel*) CMD="help"; HELP=0 ;; -v|--ver*) CMD="vers"; VERS=1 ;; --) shift; break ;; esac shift; ##remove that arg done if [ "$CMD" = "" ];then ##expect A B positionals if [ $# -ne 2 ];then HELP=2; else A=$1; B=$2; shift; shift; fi fi ##[ $PROMPT$TEST ] || { PROMPT=1; CHGARG="-p"; } ##==DEBUG; default to PROMPT until recent mods trusted; soon becomes tiresome... if [ $VERS ];then echo "webmv version:$(date -r$0 +%Y-%m-%d). Copyright 2001,2008 Eugene Reimer. Use is subject to GPL"; exit 0; fi if [ $HELP ];then echo "usage: webmv options fileA filenameB" echo " or: webmv options [dirA/]fileA dirB[/filenameB]" ##2008-11 2nd form was: dirA/fileA dirB echo "Renames fileA to filenameB, and/or moves it to dirB; also revising references in HTML files." echo "Both forms of cmdline behave like with the same operands; both forms also:" echo " o use to revise references in any HTML files;" echo " o add to a remote-renames-script to be executed by on the next website upload;" echo " o add a 301-redirect instruction to the .htaccess file and revise previous redirects;" echo " o rename any 'source' versions of the entity being renamed;" echo "the second (move) sort of cmdline:" echo " o also moves any images/pages/etc referenced by a moved HTML file, to dirB." echo "Options:" echo " -f | --force rename or move even if newname exists" echo " -k | --keeptimestamp during HTML revising, revised file keeps previous modification-timestamp" echo " -n | --nobackup during HTML revising, no copy kept of previous file contents" echo " -T | --tmpbackup during HTML revising, backup under /tmp, instead of in current directory" echo " -R | --noredirect skip the redirect update to .htaccess file" ##2009-03-21: new echo " -S | --nosource skip the renaming in source-directory" ##2009-03-21: new echo " -q | --quiet suppress all messages" echo " -t | --test show what would be done, but do nothing" echo " -p | --prompt ask user before making any change" echo " -? | --help just show this info on usage" echo " -v | --version just show version info" echo "This script may need customization before being useful for another person's file-tree." echo "NOTE: requires that filenames be minimally qualified!" exit $HELP; ##exit fi writeto() { echo -e "$1" >"$2"; } ##--write string to file - function needed to avoid grief with redirection writeapp() { echo -e "$1" >>"$2"; } ##--append string to file - function needed to avoid grief with redirection echoMSG() { [ "$MSG" = "" ] || [ $QUIET ] || echo "webmv: $MSG"; } DO_C() { ##--function to Prompt (PROMPT), or Display (TEST), or Execute (otherwise) a received cmdline if [ $PROMPT ];then echo -n "webmv: $@ -- Y/N?"; read; [[ $REPLY == [Nn]* ]] || "$@" elif [ $TEST ];then echo "$@" else "$@"; echoMSG fi } DO_Q() { ##--function to Execute quietly without asking, for a cd|chgsed-with-$CHGARG cmdline -- NOT NEEDED SINCE A NO-OP!! if [ $PROMPT ];then "$@" ##do quietly, without asking (no need to ask for cd; chg-with-$CHGARG will do its own asking) elif [ $TEST ];then "$@" ##do quietly for TEST (cd is harmless; chg-with-$CHGARG will report "would be changed" files) else "$@" fi } DO_X() { ##--like DO_C, except it s on a NO-response; for cmd so vital skipping it requires skipping everything if [ $PROMPT ];then echo -n "webmv: $@ -- Y/N?"; read; [[ $REPLY == [Nn]* ]] && exit 3; "$@" elif [ $TEST ];then echo "$@" else "$@"; echoMSG fi } enq_remote_cmd () { ##==enqueue a cmd to be done remotely by webput(lftp) local CMD=$1 if [ -e "$ROOTDIR"-queue ];then MSG="ENQUEUED CMD:$CMD" DO_C writeapp "$CMD" "$ROOTDIR"-queue ##enqueue cmd for next fi } enq_remote_mv () { ##==enqueue a mv-cmd to be done remotely by webput(lftp) local A=$PREF$1 B=$PREF$2 enq_remote_cmd "mv $A $B" } mk_redirect() { ##==make .htaccess redirect entry; local A=$PREF$1 B=$PREF$2 ##discard any B->* entry, discard A->* entry with grumbling, revise *->A entries to *->B, append the A->B entry; if [ $NOREDIRECT ];then return; fi ##2009-03-21: skip .htaccess update if --noredirect specified if [ $LOCURL ] && [ -e $ROOTDIR/.htaccess ];then ##with .htaccess, can handle any type... if [[ $B == *\.@(jpg|gif|png) ]];then return; fi ##not essential, but have been excluding images (was jpgs) ==YANK for /noci==??== DATE=$(date +%Y-%m-%d) ##get DATE; used to need it evaluated just once when used in multiple commands if [[ $A == */index.htm ]];then A=${A%index.htm}; fi ##2010-03-22: stdize SUBDIR/index.htm to just SUBDIR/ if [[ $B == */index.htm ]];then B=${B%index.htm}; fi ##2010-03-22: stdize SUBDIR/index.htm to just SUBDIR/ chg $CHGARG -c "sed ' ##chg with piped-sed-cmds to revise the redirect-portion of .htaccess file /^##==ADD 301/,\${/ \/${B//\//\\/}/d;} ##discard B-> entry /^##==ADD 301/,\${/ \/${A//\//\\/}/d;} ##discard A-> entry, need msg?? /^##==ADD 301/,\$s|\(http.*\)$A|\1$B|g ##revise ->A entries to ->B \$a##$DATE\nredirect 301 /$A $LOCURL/$B ' |sed -n 'G; s|\n|&&|; /^\([ -~]*\n\).*\n\1/d; s|\n||; h; P' ##==uniquify (for DATE-line) " $ROOTDIR/.htaccess ##NOTE one quoted-string to chg-c containing strophed ARGS TO SED!! elif [ -d $ROOTDIR-redirects ] && [[ $B == *htm ]];then ##w/o .htaccess is htm-only; as in my old webmv-OLD MSG="CREATED REDIRECT" DO_C writeto "That page has moved to $B" $ROOTDIR-redirects/$A fi } [ $QUIET ] || echo "##---webmv $AT" ##so output makes sense - needed when invoked from ##echo -n "webmv: A=$A; B=$B; PROMPT=$PROMPT; TEST=$TEST; CHGARG=$CHGARG; --BEWARE OF RECENT CHANGES--"; read ##DEBUG - chance to Ctrl+C abort ##set -xv CWD=$(pwd); x=${CWD#/}; PROJ=${x%%/*} ##set CWD and PROJ; eg: PROJ==er|noci|debwendon ROOTDIR=$CWD; while [[ $ROOTDIR == /*/*/* ]];do ROOTDIR=${ROOTDIR%/*}; done ##2008-11: need ROOTDIR; assume it is two-level name PREF=${CWD#$ROOTDIR}; PREF=${PREF#/}; if [ $PREF ];then PREF=$PREF/; fi ##2008-11: need PREF the minimally qualified curdir; empty or with ending slash . WEBURL $ROOTDIR ##2008-11-05: map $ROOTDIR into $LOCURL; for $LOCURL null mk_redirect will do nothing ##echo "ROOTDIR=$ROOTDIR PREF=$PREF LOCURL=$LOCURL ok?"; read ##DEBUG if [ -d $B ] || [[ $B == */* ]];then ##2008-11: was $A == */* ##==================== ##--the (MOVE) case -- ##==================== ##if [ -d $B ] && [[ $B == */* ]];then echo "multi-level directories not supported"; exit 2; fi ##supports at most one-level of directory below $ROOTDIR DIRA=.; if [[ $A == */* ]];then DIRA=${A%/*}; fi DIRB=$B; NEW=${A##*/}; if [[ $B == */* ]];then DIRB=${B%/*}; NEW=${B##*/}; fi [ -e "$DIRB" ] || { DO_X mkdir $DIRB; enq_remote_cmd "mkdir $PREF$DIRB"; } ##==are moves always done with CWD==ROOTDIR?? is remote-mkdir needed?? [ -d "$DIRB" ] || { echo "webmv: FATAL ERROR $DIRB is not a directory"; exit; } [ $FORCE ] || { [ -e "$DIRB/$NEW" ] && { echo "webmv: FATAL ERROR $DIRB/$NEW exists"; exit; }; } MSG=; DO_X /bin/mv -- "$A" $B; if [ $? -ne 0 ];then exit; fi ##do the local move enq_remote_mv $A $DIRB/$NEW ##enqueue remote-mv cmd for next webput(lftp) mk_redirect $A $DIRB/$NEW ##make redirect via .htaccess chgsed $CHGARG "s|$A|$DIRB/$NEW|g" $ROOTDIR/*{htm{,l},txt,css} ##update symbolic ptrs in HTML-files (and CSS?) chgsed $CHGARG "s|$A|../$DIRB/$NEW|g" $DIRA/*{htm{,l},txt,css} ##update symbolic ptrs in HTML-files (and CSS?); revised 2008-11-12 chgsed $CHGARG "s|$A|$NEW|g; s|${A#$DIRA}|$NEW|g" $DIRB/*{htm{,l},txt,css} ##update symbolic ptrs in HTML-files (and CSS?); new 2008-11; revised 2008-11-12 if [[ $NEW == *htm ]];then ##for htm, also move referenced images/pages; 2008-11: scrapped the cd-to-$DIRA for F in $DIRA/*;do [ -e $F ] || continue ##2008-11: was jpg only, then jpg|gif|png|htm|js|css|txt; then ANY with msg (below) if ! grep -q "[={\"]${F##*/}" $DIRB/$NEW;then continue; fi ##2008-11-12: stricter test, prevchar [=("], to reduce false matches if [[ $F == *htm ]];then webmv $CHGARG "${F#./}" $DIRB/${F##*/} ##2008-11-13: recursive webmv for an also-moved htm file?? else MSG="ALSO MOVED: ${F#./}" DO_C /bin/mv -b -- "${F#./}" $DIRB/${F##*/} enq_remote_mv "${F#./}" $DIRB/${F##*/} mk_redirect "${F#./}" $DIRB/${F##*/} ##2008-11-12: it may need a redirect; 2009-12-20: let mk_redirect decide... fi if ! [[ $F == *@(jpg|gif|png|htm|js|css|txt) ]];then echo "webmv: ==$F has unusual ending"; fi ##2008-11-14: warn if unusual ending (may yank) done fi ##==if $DIRA became empty, rmdir?? A=${A##*/}; B=$NEW; if [[ $A == $B ]];then exit 0; fi ##if no name-change, we're done; otherwise continue with A->B source-renaming else ##======================= ##-- the (RENAME) case -- ##======================= [ $FORCE ] || { [ -e "$B" ] && { echo "webmv: FATAL ERROR $B exists"; exit; }; } MSG=; DO_X /bin/mv -- "$A" $B; if [ $? -ne 0 ];then exit; fi ##do the local rename if [[ $ROOTDIR != $CWD ]];then DO_Q chgsed $CHGARG "s|$A|$B|g" {,$ROOTDIR/}*{htm{,l},txt,css} ##update symbolic ptrs in all HTML files, also CSS?? else DO_Q chgsed $CHGARG "s|$A|$B|g" *{htm{,l},txt,css} ##update symbolic ptrs in all HTML files, also CSS?? fi enq_remote_mv "$A" $B ##enqueue remote-mv cmd for next webput(lftp) mk_redirect "$A" $B ##make redirect via .htaccess if [ $NOSRC ];then exit; fi ##2009-03-21: skip source-renaming if --nosource specified if [[ $CWD == /noci/website* ]];then for D in ../website[0-9][0-9][a-z][a-z][a-z][0-9][0-9];do ##matches only website01oct01 these days -- revised 06nov to not match *01oct01-root* DO_Q cd $D if [ -e "$A" ];then echo "webmv: IN BACKUP DIRECTORY $D:" [ $FORCE ] || { [ -e "$B" ] && { echo "webmv: FATAL ERROR $B exists"; exit; }; } MSG="renamed $A --> $B" DO_C /bin/mv "$A" $B ##do rename in copy of "orig" website DO_Q chgsed $CHGARG "s|$A|$B|g" *{htm{,l},txt,css} ##update symbolic ptrs in "orig" HTML files; used to have: [ $? -eq 0 ] && fi done fi fi ##======================================== ##--the "Source" renaming under /pix/PROJ* ##======================================== if [ $NOSRC ];then exit; fi ##2009-03-21: skip original-renaming (source-renaming) if --nosource specified if [[ $CWD == /pix* ]];then exit; fi ##skip source-renaming if invoked from a pix directory - 05dec ## [[ $A != *[a-z_]*.* ]];then exit; fi ##2008-10-05 skip allcaps filename; WAS OVERKILL (fixed Av-test+Ab-matching, so underscoreless-test handles) ##split filename $A into relevant pieces At=${A##*.} ##save At filetype part (e.g. "jpg") Ab=${A%.*} ##get Ab filename without filetype part Ax=$Ab;Asz=; while [ "$Ax" != "${Ax%[0-9]}" ];do Asz=${Ax:0-1:1}$Asz; Ax=${Ax%[0-9]}; done ##get Ax filename without SIZE part Av=$Ax;Aed=; while [ "$Av" != "${Av%[A-Z]}" ];do Aed=${Av:0-1:1}$Aed; Av=${Av%[A-Z]}; done ##get Av filename less alteration letters B C etc; 2008-10-05: quotes ##echo "Av=$Av Aed=$Aed Asz=$Asz At=$At" ##debug ##split filename $B the same way Bt=${B##*.} ##save Bt filetype part (e.g. "jpg") Bb=${B%.*} ##get Bb filename without filetype part Bx=$Bb;Bsz=; while [ "$Bx" != "${Bx%[0-9]}" ];do Bsz=${Bx:0-1:1}$Bsz; Bx=${Bx%[0-9]}; done ##get Bx filename without SIZE part Bv=$Bx;Bed=; while [ "$Bv" != "${Bv%[A-Z]}" ];do Bed=${Bv:0-1:1}$Bed; Bv=${Bv%[A-Z]}; done ##get Bv filename less alteration letters B C etc; 2008-10-05: quotes ##echo "Bv=$Bv Bed=$Bed Bsz=$Bsz Bt=$Bt" ##debug if [ "$Ax" = "$Bx" ];then exit; fi ##skip source-renaming if only SIZE or FILETYPE being renamed ## [ "$Av" = "" ];then exit; fi ##05oct: STILL MISBEHAVES on allcaps filename; 2008-10-05: quoted Av/Bv tests + FPAT-FIX obsoletes ##-- ##--QUESTION-1: whether to match using $Ab or $Ax or $Av: ##-- Answer: normally want $Av, eg: website has only the Cropped version but want both originals renamed; but want Ab for htm or underscoreless-image; ##--QUESTION-2: how to handle changes to the "editing letters" B C etc: ##-- Answer: consider X_CB400.jpg-->X_BC400.jpg -- do apply that part to matching originals ##-- ##--REVISED 03oct14: different matching for HTML files, match on $Ab, avoid breaking off SIZE etc ##-- mount /sdb6; ##05may: do renames under /sdb6 also ==beware of exit leaving sdb6 mounted== for D in /pix/$PROJ* /sdb6/$PROJ*;do ##05may was: /$PROJ/src /pix/$PROJ* [ -d "$D" ] || continue DO_Q cd $D; ((ct=0)) FPAT=$Av; if [ "$At" = "htm" ] || [[ $Ab != *_* ]];then FPAT=$Ab; fi ##2008-10-05: ==FPAT-FIX== use full-match for htm or underscore-less-name for F in $FPAT*;do ##2008-10-05: ==FPAT-FIX== was:for F in $Av*;do [ -e "$F" ] || continue ((++ct==1)) && echo "webmv: NOW IN DIRECTORY $D" Ft=${F##*.}; [ "$Ft" = "$F" ] && Ft=""; ##filetype can be missing here, even if never so in $A or $B Fb=${F%.*} Fx=$Fb;Fsz=; while [ "$Fx" != "${Fx%[0-9]}" ];do Fsz=${Fx:0-1:1}$Fsz; Fx=${Fx%[0-9]}; done Fv=$Fx;Fed=; while [ "$Fv" != "${Fv%[A-Z]}" ];do Fed=${Fv:0-1:1}$Fed; Fv=${Fv%[A-Z]}; done ##2008-10-05: quotes ##echo "Fv=$Fv Fed=$Fed Fsz=$Fsz Ft=$Ft" ##debug if [ "$At" = "htm" ] || [[ $Ab != *_* ]];then ##for htm; 06nov: also for filename WITHOUT UNDERSCORE [ "$Fb" = "$Ab" ] || continue; ##skip unless have match on $Ab (for htm document or nonstd image-filename) ==OBSOLETED by FPAT-FIX above== NEW=$Bv$Bed$Bsz.$Ft; ##form newname using $Bb (for htm document or nonstd image-filename) else if [ "$Fed" = "$Aed" ];then ed=$Bed; else ed=$Fed; fi NEW=$Bv$ed$Fsz.$Ft; ##form newname for photo, using size and possibly editing-letters from $F fi [ "$F" = "$NEW" ] && { echo "webmv: $F NAME STAYS SAME"; continue; } ##skip if name stays the same [ $FORCE ] || { [ -e "$NEW" ] && { echo "webmv: $NEW NEWNAME EXISTS"; continue; }; } ##skip if newname exists ## ##echo -n "OK to rename $F-->$NEW -- Y/N?"; read; [[ $REPLY == [Nn]* ]] && continue ##==DEBUG ONLY; CONSIDER using --prompt instead of unyanking this? MSG="renamed $F --> $NEW" DO_C /bin/mv "$F" $NEW ##rename DO_Q chgsed $CHGARG "s|$F|$NEW|g" *{htm{,l},txt,css} done done cd /; umount /sdb6 ##note: avoid curdir being on sdb6, or umount will say "device is busy"... exit ============== OBSOLETE BITS: ============== From mk_redirect: ##==version below worked, but for nicer output want single chg... #chgsed $CHGARG " ##(1) chgsed to revise the redirect-portion of .htaccess file # /^##==ADD 301/,\${/ \/${B//\//\\/}/d;} ##discard B-> entry # /^##==ADD 301/,\${/ \/${A//\//\\/}/d;} ##discard A-> entry, need msg?? # /^##==ADD 301/,\$s|\(http.*\)$A|\1$B|g ##revise ->A entries to ->B # \$a##$DATE\nredirect 301 /$A $LOCURL/$B #" $ROOTDIR/.htaccess ##end-of chgsed to revise the .htaccess file #chg $CHGARG -c "sed -n 'G; s|\n|&&|; /^\([ -~]*\n\).*\n\1/d; s|\n||; h;P'##(2) chg to uniquify .htaccess (for DATE-line); NOTE ARGS TO SED #" $ROOTDIR/.htaccess From mk_redirect, after line: if [ $LOCURL ] && [ -e $ROOTDIR/.htaccess ];then: if [[ $ROOTDIR == /er* && $B =~ '([0-9][0-9]|[2-9])[0-9][0-9].jpg' ]];then ##2009-12-20: special-case redirect for an invented-htm on ER-site; YANKED same day A=${A/.jpg/.htm}; B=${B/.jpg/.htm} ##2009-12-20: to be redirected as samename.htm fi =========== CHANGE-LOG: =========== 2005may: introduced parameters mostly for passing to ; 2005may: inlined former ; 2005may: apply source-renaming to /sdb6 as well as to /pix; moved /noci/src to /pix/noci-src, in order to simplify places to be checked for originals. 2005may: finished $PROMPT support using neater method: DO function, invoke as: DO chg... then it does the prompting (PROMPT), or test-output (TEST), or executing the cmd (otherwise); ended up with 3 variants: DO_C DO_Q DO_X (although DO_Q is a no-op); ==CONSIDER: just one DO function, and it tests $1 == cd/chg/... to get the variant behaviours?? OR: one DO function with params: -U|--dontAsk -X|--exitOnNO --msg"xxx" to replace the setting of MSG= ==CONSIDER: normal behaviour is to echo "doing..." for the Neither-PROMPT-nor-TEST case; but support --quiet to suppress; could then remove some uses of and of MSG/--msg Old Notes on improvements needed: a prompting "read" does NOT work when script invoked by output being piped into ; can write to a tmpfile, then execute it, and that way reads in this script will work. BEWARE: using webmv on names like LOGO-NOCI200.gif produces unpleasant surprise, during source-renaming --!!-- last part of name ALL-CAPS gets stripped as "alteration letters" (is OK to use ALL-CAPS followed by Underscore) TO FIX: strip alteration-letters ONLY when filename contains underscore; 2006nov: tried to implement this overdue improvement, by treating underscore-less filename just like HTML filename -- still inadequate; 2008-10-05: FIXED, see notes at end; 2006may: did some work on the Revising Of Redirects: (1) remove any redirect that conflicts with a newname -- DONE but UNTESTED; this will prevent self-referential redirects (that arise from renaming or moving back to former name/location) as well as conflicting ones (when newname has been used before, then renamed or moved) (2) FURTHER IMPROVEMENT needed, to prevent forming ../dir/../dir redirects: need to simplify to ONE KIND of redirect (all in qualified form); TROUBLESOME part: only want qualified redirects for the /er subdirs, BUT NOT for /noci--!!-- NOTE: the MOVE-case is only for the "multiple-site" kind of site, like "er"; but RENAME-case is useful anywhere. UNFINISHED: see <> - is ready to convert existing ones to std form. ==NOTE-2008: this is no longer needed; was only needed because of the multi-site structure at Shaw (ereimer reimer[2-9]...) 2008-Apr: getting error-msgs from mount & umount, "already mounted" and "not mounted"; AND sdb6 renaming not being done--!!-- because sdb6 is 100% full--??-- indeed THAT'S THE ANSWER; after freeing up some space, it works again!! --cleanup needed under sdb6, because of renames that went undone; did by redoing the entire copy after buying bigger drive; 2008-10-05: webrename "^PB" "POD" PB*, got error-msg "[: P: unary operator expected" webmv-lines: 197 205 231 <--don't recall seeing this before==??== line197,205 due to Av, Bv becoming empty on an ALLCAPS-filename; line231 due to Fv doing so, on: /pix/noci0509-Video-PSA/PSA.mpg; (Av didn't actually become empty, as test failed when Av was down to a single Uppercase-char; EXPLAINS why the 05oct attempt failed to fix) (2) also got way too many "NOW IN DIRECTORY" msgs, during: webrename "^PB" "POD" PB* <--jpg+htm files, received msg for many noci* dirs due to faulty $Av but not during: webrename SmallWhiteVolunteers.htm FT2008-NCC.htm <--one .htm file FIX-1: the filenames were ALLCAPS, so removing alteration-letters produced empty-string -- fixed Av/Bv/Fv tests by adding quotes (see "2008-10-05"); FIX-2: avoid spurious "IN DIRECTORY" msgs, by revising the for-loop-pattern (see "==FPAT-FIX=="); QUESTION: any damage to filenames under /pix/noci*: saw no spurious renamings; saw chgsed msgs only for podbook.htm menuPB.htm {PB,POD}[0-9][0-9].htm 2008-11: MAJOR REWRITE -- not nearly all altered lines carry a "2008-11" comment!! (1) replace OBSOLETE code specific to Multi-Site file-structure: MAINDIR, the entire MOVE-case (former webdirmv), $ROOTDIR-clean-needed; NOTE: keep "move" support but now for subdirs; eg: moving htm-file to different dir => moving jpg's also; NOTE: the ROOTDIR now somewhat like the former MAINDIR, wrt html-revising; NOTE: touching $ROOTDIR-clean-needed is obsolete, since no longer needed by WEBUT; NOTE: the "move" case now supports renaming at same time (with source-renaming too); (2) REDIRECT-support: instead of creating subfile of ROOTDIR-redirects/, now modify ROOTDIR/.htaccess adding a 301-redirect statement; HAVE converted {debwendon,er,noci} .htaccess: adding "##==ADD 301-REDIRECTS HERE==" at end, then any recent redirects converted from $1-redirects/* (debwendon had 3 from 2008-06; er had none; noci had several from 2008-06-15 and 2008-10-05, plus menu* from 2008-09 done manually); NOTE: new method allows redirect for any file-type (previously HTML only); note: there is less reason to redirect images, and doing so would make .htaccess over-large; BUT do want to redirect TXT & PDF files; note: presently adding redirect for any non-jpg if explicitly moved, htm-only for "also moved" (briefly did for any if explicit...) for A->B rename: discard any B->* entry, discard A->* entry with grumbling, revise *->A entries to *->B, append an A->B entry; but begin with "##YYYY-MM-DD" comment; ARGH, only entire-line comments are allowed on .htaccess:-( HAVE revised comments in all three .htaccess files, so they'll survive duplicate-removal; 2008-11-11: EG: webmv pix060813-B.htm 20060813-B/index.htm when pix060813.htm had a link to pix060813-B.htm the link got revised to 20060813-B/index.htm -- correct at the time, but became broken when that file was moved (pix060813.htm-->20060813/index.htm); when moving an htm file containing an unqualified-link-to-HTM, (a) add leading slash or dot-dot-slash, (b) a Warning Message, (c) move it too?? in this example the 2 dirs need to be combined, so Warning would've been best; however: am going to an HTM-file for each image => best to "also move" HTM files (done 2008-11-12) this example demostrates another flaw: moving jpg files that are referenced by another htm page, ought to produce a Warning Message?? ==note: this script is already slow (when in large dir) ==> better to make separate link-integrity-checking script: see webclean WEBXREF-checkForBrokenLinks; EG2: webmv 20060813-B/index.htm 20060813/index-ALT.htm that link became 20060813/index-ALT.htm, ought to be just index-ALT.htm (fixed 2008-11-12) note: .htaccess was correct; website-queue also correct; 2008-11-11: on "also moved", now doing enq_remote_mv (another difference from the multi-site methods); could also add redirect, but won't for images on "also moved", now do GIF, PNG as well as JPG images; to improve msgs: (1) in move, now do HTML-revising after enqueue_mv; (2) ==combine the 2 sed-cmds that revise .htaccess using pipe... have revised genByCaption script wrt reorged filenames, and new -ALT convention; TO RENAME a DIRECTORY: webmv OLDDIR/index.htm NEWDIR; EG3: webmv KPLR/pixKPLReimer06jun.htm 20060610-KPLR/index.htm; EG4: webmv KPLR/pixKPLReimer06jun-ALT.htm 20060610-KPLR/index-ALT.htm <--FIXME: failed to revise link in preceding, because matching with dir EG5: webmv speciesListForOrchidFestivalAtSenkiw2007jun17.htm 20070614 <--FIXME: incorrectly revised the link in 20070614/index.htm (same as EG2) 2008-11-12: "also move" now includes htm-files; made matching stricter to avoid false matches; an also-moved htm file does get a redirect; chgsed-HTML-revision: now doing with leading-slash in $DIRA, without $DIRB on files in $DIRB - to fix the EG2/EG5 problem; $DIRB files now also matched without leading $DIRA - to fix EG4 problem; note: chgsed is recursive, so doing in $ROOTDIR would do subdirs too; however am doing on *htm to prevent recursion => OK for dir-dependent revisions... I'm baffled by my rename-case doing revision on CSS-files; I use them so sparingly, and find no example that might need this; ==however, if needed then surely the move-case ought to do them too?? COMBINED the SED-cmds using a PIPE -- altho confused about the quoting? whether chg needs work wrt strophs? EG6: webmv -p shopping.htm NOPERCART-DEMO1/shopping.htm <--the chg on .htaccess worked, HURRAH!! --many false matches when revising: nopercart.HTM shopping-old-browser-methods.htm shoppingcart.htm shoppingthanks.htm then same files again for DIRA-revisions as ./nopercart.htm etc; all were refs to shopping.htm -- many of these false matches seem unavoidable; a few would've been avoided by stricter matching, prevchar=="="; for also-moved htm-file, redirect & queued-mv had LHS like: /./shoppingcart.htm <--have removed "./"; it moved shoppingcart.htm, but not the files it refers to -- fixed by doing recursive webmv for an also-moved HTM file; ==FIXME: avoid duplicate revision during move-case: when DIRA or DIRB same as ROOTDIR; for also-moved js, may want redirect?? did manually for nopercart.js; but in general js needs it no more than an image... EG7: considered using mv rather than webmv to move remaining shopping*htm to NOPERCART-DEMO1, to avoid false matches, but do want -queue .htaccess stuff; ==> may need a NO-REVISION option to do the mv and the -queue .htaccess updates, but NOT the HTML revision?? (false matches in nopercart.htm, ought to be easily undone via unchg since done quickly); ARGH: nopercart.HTM was moved--!!-- as an also-moved when doing shoppingthanks.htm -- may need to fix the stricter matching?? --NOPE: shoppingthanks.htm contains: Our Frontpage ERGO, THE ALSO-MOVE WAS CORRECT AFTER ALL; made an inter-page link in 20080704/index.htm (to ../20080701/index.htm) -- may be the first ever? might cause grief on a webmv? ==FIXME: when using --prompt, nicer to have only one prompt for mv & enq_remote_mv cmds -- especially for each also-moved... could live without a msg for Enqueued-move -- since not getting such a detailed msg for the Redirect (just the .htacces changed...); EG8a: webmv 20060610-KPLR/index.htm KPLReimer <--directory-renaming seems unnatural => may enhance webmv for dir-rename?? EG8b: webmv 20060610-KPLR KPLReimer <--AHA this already works with present code; may need to add index.htm to both sides of Redirect tho; 2008-11-13: also-moving: use recursive webmv for an htm file, so its images/pages will also be moved; (left old code since may yet flip) also-moving: include .txt files; to match programs could use file|grep text?? ==but why not ANY file matched by the moved page?? 2008-11-14: also-moving: do for ANY filetype, with warning-msg for unusual ending (temp?); ==stricter matching on the HTML-revising?? EG9: webmv computerprograms.htm programs/index.htm <--also-moved bird-puzzle.icn and the shell-scripts (ending-less names); got Warning-msg for bird-puzzle.icn img2transparent mkfavicon mkfavicon-transparent; but not for jsminify--??-- AHA, the =~ matching is unanchored, so the "js" matched; see EXAMPLES-GLOBS+ExtendedRegexes-Anchored-vs-Unanchored; fixed the test for that Warning-msg, to work with this unanchored matching -- the backslashed version got very ugly, quoted considerably less so; if ! [[ $F =~ '(jpg|gif|png|htm|js|css|txt)$' ]];then echo "webmv: ==WARNING: $F has unusual ending"; fi 2008-11-16: avoid making redirect for explicitly moved jpg -- almost always want images excluded (especially from WEBSCALE), most everything else to be redirected?? 2008-12-12: revised {htm,css}-->{htm,html,css} also a few htm-->{htm,html,css} isn't needed for my own stuff, but when working on downloaded copies of other people's... (eg: /pix/er-TheLittlePrince-Illustrations-small-set) 2009-03-21: new options: --nosource --noredirect 2009-04-19: for the new style of "nav" code, via SSI-includes of nav1-head.txt, nav2-body.txt, need to revise nav*txt as tho HTML; handled by revising *.{htm,html,css} --> *{htm{,l},txt,css}; hmm, revising all *txt ought to be OK; do still want *html revision; 2009-12-20: mk_redirect: if in /er*, then treat move/rename of 3/4-digits.jpg as an operation on samename.htm; ie: gets a redirect; <--YANKED; YANKED almost immediately; am about to create 175 new subdirs, moving some 5,000 images, and that sounds like too much for .htaccess; DECIDED ON: having pixpage handle not-found jpg; CONSIDER: a CGI-handler for all file-not-found cases; would still want ability to log as a 404 if nothing helped; doing via 404-handler... 2010-03: mk_redirect: revised URL-->LOCURL; 2010-03-22: in mk_redirect, stdize SUBDIR/index.htm to just SUBDIR/ QUESTION: should both LHS and RHS of a redirect get the index.htm-STRIPPING (my first thought was only RHS gets it)--??-- (A) if only RHS gets such stripping then: vars A and B are left unchanged (wrt index.htm), new vars AS, BS have had index.htm-STRIPPING applied; revising old ->A entries to ->B, need to use AS and BS; discarding old B-> entries, need to use B (not BS); making new A->B entry, need to use A and BS; (B) when both LHS and RHS get such stripping: both $A and $B are modified, and the chgsed-cmds remain unchanged; ==going with (B) BOTH LHS and RHS get index.htm-STRIPPING, but may need to see examples before feeling confident?? 2010-11-10: ==FIXME: quit if mv fails; was surprised that it didn't; 2011-01-06: BEWARE: bash-v4 has changed the meaning of =~ within double-square-brackets: specifically what quoting in RHS does; best to avoid it, using == and the extglob extensions since those work everywhere; added: shopt -s extglob revised: [[ $B =~ '\.(jpg|gif|png)$' ]] --> [[ $B == *\.@(jpg|gif|png) ]] [[ $F =~ '(jpg|gif|png|htm|js|css|txt)$' ]] --> [[ $F == *@(jpg|gif|png|htm|js|css|txt) ]]