1#!/bin/sh 2# 3# @(#) /u/des/src/sortmail/sortmail 1.20 00/07/28 18:37:09 4# 5# sortmail: automate decomposemail & recomposemail 6# 7# See "USAGE" and "SUMMARY" below for more information. 8# 9# 10/96, D.Singer 10# 11# 12# Copyright (c) 1998 by Daniel E. Singer. All rights reserved. 13# Permission is granted to reproduce and distribute this program 14# with the following conditions: 15# 1) This copyright notice and the author identification below 16# must be left intact in the program and in any copies. 17# 2) Any modifications to the program must be clearly identified 18# in the source file. 19# 20# Written by: 21# Daniel E. Singer 22# UNIX Systems Administrator 23# Department of Computer Science 24# Duke University, Durham, NC 25# Phone: 919/660-6500 26# Email: des@cs.duke.edu 27# 28 29 30# 31# add a PATH if needed 32# 33#PATH='/usr/bin:/bin:/usr/sbin:/sbin:/usr/ucb:/usr/bsd:/usr/etc:/usr/gnu/bin:/usr/local/bin' 34#export PATH 35 36PATH=$PATH:/home/lasse/work 37export PATH 38 39PROG=`basename "$0"` 40 41umask 077 # create files and dirs with restrictive perms, 42 # since this involves email; 43 44WORK_DIR="SM_WORK" # where work will be done 45BACKUP_DIR="SM_BACKUP" # where backups will be stored 46 47# 48# SRC_DIR and SRC_PATH refer to the relative starting location of this script; 49# usually we will be working from a subdirectory; these are altered when 50# using the -H (Here) flag; 51# 52SRC_DIR=".." 53SRC_PATH="../" 54 55# 56# these scripts must be accessible for any of this to work; 57# add paths if needed; 58# 59DECOMPOSE="decomposemail" 60RECOMPOSE="recomposemail" 61 62USAGE=" 63Usage: $PROG [-chHmMyYrRvx] mbox... 64 65 -c move current month mbox back to source dir mbox, implies -r 66 (use with -m, -M, -y, or -Y); 67 -h help, print help message and exit; 68 -H here, do work in this dir instead of in \"./$WORK_DIR\" dir; 69 -m sort to monthly mailboxes of type mbox.YYMM; 70 -M sort to monthly mailboxes of type YYMM/mbox; 71 -y sort to yearly mailboxes of type mbox.YYYY; 72 -Y sort to yearly mailboxes of type YYYY/mbox; 73 with -m, yields YYYY/mbox.MM; 74 with -M, yields YYYY/MM/mbox; 75 -r remove the original mailbox after sort/merging; 76 -R recurse, redo any appended mailboxes (use with -m, -M, -y, 77 or -Y); 78 -v verbose, more messages; 79 -x don't make any backup copies in \"./$BACKUP_DIR\" dir; 80" 81 82SUMMARY=" 83'sortmail' automates the scripts 'decomposemail' and 'recomposemail', 84and provides some additional functionality. 85 86Default behavior is to take each mbox (mailbox) argument, make a copy, 87decompose it into individual message files, and then recompose the 88messages, ordered by date in increasing order. 89 90With the '-m' flag, the messages are re-assembled into separate files 91per month, mbox.YYMM. For example, \"mlist.9801\". 92 93With the '-M' flag, the messages are re-assembled into separate files 94per month in subdirectories, YYMM/mbox. For example, \"9801/mlist\". 95 96With the '-y' flag, the messages are re-assembled into separate files 97per year, mbox.YYYY. For example, \"mlist.1998\". 98 99With the '-Y' flag, the messages are re-assembled into separate files 100per year in subdirectories, YYYY/mbox. For example, \"1998/mlist\". 101If combined with '-m', the files have a month suffix, for example, 102\"1998/mlist.01\". If combined with '-M', the files have an additional 103month sudirectory, for example, \"1998/01/mlist\". 104 105With the '-c' flag (along with -m, -M, -y, or -Y), the mbox file for 106the current month (if any) will be moved into the location of the 107original mbox. 108 109With the '-R' flag (along with -m, -M, -y, or -Y), when a month file 110is combined with one that already exists, the resulting file will be 111re-sorted. If any such existing files are compressed (.Z or .gz), 112they will be uncompressed and then recompressed after being modified. 113 114With the '-H' flag, all work is done in the current directory instead 115of in the \"./$WORK_DIR\" directory. This reduces the usefulness of 116some of the other options, and is a bit riskier regarding your original 117mboxes. 118 119By default, all work is done in a subdirectory \"./$WORK_DIR\", and 120all files to be modified are backed up in a subdirectory \"./$BACKUP_DIR\". 121These subdirectories are created if they don't already exist. 122 123Due to copies made during the sorting process, you should have enough 124additional space in your current partition and/or quota to hold three 125full copies of each original mbox. 126 127Much of this can be accomplished using 'decomposemail' and 'recomposemail' 128directly, but many more manual steps are required. 129" 130 131# for use with 'eval' 132CMD='echo "$PROG: $cmd" >&2; eval "$cmd"' 133 134CURRENT=0 # current flag (-c) 135DEBUG=0 # debug flag (-d) 136HERE=0 # here flag (-H) 137MFLAG=0 # month flag (-m), merge to mbox.yymm 138MMFLAG=0 # Month flag (-M), merge to yymm/mbox 139PASS_MFLAG= # month flag to pass to other scripts 140YFLAG=0 # year flag (-y), merge to mbox.yyyy 141YYFLAG=0 # Year flag (-Y), merge to yyyy/mbox 142PASS_YFLAG= # year flag to pass to other scripts 143RECURSE=0 # recurse flag (-R) 144REMOVE=0 # remove flag (-r) 145VERBOSE=0 # verbose flag (-v) 146PASS_VFLAG= # verbose flag to pass to other scripts 147BACKUP=1 # backup flag (! -x) 148 149# these are some possible combination of the date sort flags, 150# and are compared against SMODE 151no_SORT="0000" # no date sorting at all 152 m_SORT="0001" # -m 153 M_SORT="0011" # -M 154 y_SORT="0100" # -y 155 Y_SORT="1100" # -Y 156Ym_SORT="1101" # -Y and -m 157YM_SORT="1111" # -Y and -M 158 SMODE="$no_SORT" # sort mode, a combination of the date sort flags 159 160USE_DATES=0 # will be using dates (any of -[mMyY]) 161USE_DIRS=0 # will be using subdirs (any of -[MY]) 162 163# 164# platform specific settings 165# 166AWK=awk 167SYS="`uname -sr`" # OS type 168case "$SYS" in 169 "SunOS "*) 170 AWK=nawk 171 esac 172 173# 174# function to append items to a newline-separated list; 175# list goes to stdout; 176# Usage: NEW_LIST=`append_list "$LIST" "$ITEM"` 177# 178append_list() { 179 for _AL_ARG do 180 [ "$_AL_ARG" ] && echo "$_AL_ARG" 181 done 182 return 183} 184 185# 186# function to move a file to a unique name with numeric extension; 187# eg, file => file.1; 188# argument should be the path to a file 189# Usage: rotate_file "$FILE" 190# 191rotate_file() { 192 _RF_FILE="$1" 193 if [ -f "$_RF_FILE" ]; then 194 _RF_EXT=1 195 while [ -f "$_RF_FILE.$_RF_EXT" ]; do 196 _RF_EXT=`expr "$_RF_EXT" '+' '1'` 197 done 198 cmd="mv \"$_RF_FILE\" \"$_RF_FILE.$_RF_EXT\"" 199 eval "$CMD" || 200 return 1 201 fi 202 return 0 203} 204 205# 206# process command line options 207# 208 209syntax_error() { 210 echo "$PROG: option syntax error." >&2 211 echo "$USAGE" >&2 212 exit 1 213} 214 215unknown_opt() { 216 echo "$PROG: unknown option \"$OPT\"." >&2 217 echo "$USAGE" >&2 218 exit 1 219} 220 221#arg_syntax_check() { 222# [ "$1" -lt 2 ] && syntax_error 223#} 224 225while [ "$#" -gt 0 ]; do 226 OPT="$1" 227 case "$OPT" in 228 # options without arguments 229 -c) # replace original mbox with current month 230 CURRENT=1 231 REMOVE=1 232 ;; 233 -d) # debug, many commands are not executed 234 echo "$PROG: debug mode." >&2 235 CMD='echo "$PROG: $cmd" >&2' 236 DEBUG=1 237 ;; 238 -h) # help 239 echo " 240<< `$AWK <&- 'BEGIN { print toupper(\"'\"$PROG\"'\"); }'` >> 241$SUMMARY$USAGE" 242 exit 0 243 ;; 244 -H) # do the work in this dir, not "./$WORK_DIR" 245 HERE=1 246 SRC_DIR="." 247 SRC_PATH= 248 ;; 249 -m) # sort to mbox.YYMM 250 MFLAG=1 251 PASS_MFLAG=" -m" 252 ;; 253 -M) # sort to YYMM/mbox 254 MMFLAG=1 255 PASS_MFLAG=" -M" 256 ;; 257 -y) # sort to mbox.YYYY 258 YFLAG=1 259 PASS_YFLAG=" -y" 260 ;; 261 -Y) # sort to YYYY/mbox 262 YYFLAG=1 263 PASS_YFLAG=" -Y" 264 ;; 265 -r) # remove the original 266 REMOVE=1 267 ;; 268 -R) # recurse, resort appended files 269 RECURSE=1 270 ;; 271 -v) # verbose 272 VERBOSE=1 273 PASS_VFLAG=" -v" 274 ;; 275 -x) # don't make backup copy 276 BACKUP=0 277 ;; 278 # # options with arguments 279 # -c) 280 # CFLAG=1 281 # arg_syntax_check "$#" 282 # CARG="$2" 283 # shift 284 # ;; 285 --) # no more flags 286 shift 287 break 288 ;; 289 290 # unknown option 291 -?) 292 syntax_error 293 ;; 294 # compound option 295 -??*) 296 # break up a compound option 297 NEW_OPTS=`$AWK 'BEGIN { 298 OPT_STR = "'"$OPT"'"; 299 LEN = length(OPT_STR); 300 NEW_OPTS = ""; 301 STATUS = 0; 302 for (POS=2; POS+0 <= LEN; ++POS) { 303 OPT = substr(OPT_STR,POS,1); 304 if (OPT !~ /[a-zA-Z0-9_]/) 305 STATUS = 1; 306 NEW_OPTS = NEW_OPTS " -" OPT; 307 } 308 print NEW_OPTS; 309 exit STATUS; 310 }' <&-` || { 311 syntax_error 312 } 313 shift 314 if [ "$#" -gt 0 ]; then 315 set -- $NEW_OPTS "$@" 316 else 317 set -- $NEW_OPTS 318 fi 319 continue 320 ;; 321 # end of options, just command arguments left 322 *) 323 break 324 esac 325 shift 326 done 327 328# some options don't mix 329case "$MFLAG$MMFLAG" in 330 11) 331 echo "$PROG: use only one of -m and -M." >&2 332 echo "$USAGE" >&2 333 exit 1 334 ;; 335 01) 336 # this will make some tests below easier 337 MFLAG=1 338 esac 339case "$YFLAG$YYFLAG" in 340 11) 341 echo "$PROG: use only one of -y and -Y." >&2 342 echo "$USAGE" >&2 343 exit 1 344 ;; 345 01) 346 # this will make some tests below easier 347 YFLAG=1 348 esac 349 350[ "$MFLAG" = 1 -o "$YFLAG" = 1 ] && USE_DATES=1 351[ "$MMFLAG" = 1 -o "$YYFLAG" = 1 ] && USE_DIRS=1 352 353case "$RECURSE$USE_DATES" in 354 10) 355 echo "$PROG: -R only works with -m, -M, -y, or -Y." >&2 356 echo "$USAGE" >&2 357 exit 1 358 esac 359case "$CURRENT$USE_DATES" in 360 10) 361 echo "$PROG: -c only works with -m, -M, -y, or -Y." >&2 362 echo "$USAGE" >&2 363 exit 1 364 esac 365case "$RECURSE$HERE" in 366 11) 367 echo "$PROG: -R and -H do not mix." >&2 368 echo "$USAGE" >&2 369 exit 1 370 esac 371# 372# check for other bad date option combos, and set SMODE (sort mode) 373# 374SMODE="$YYFLAG$YFLAG$MMFLAG$MFLAG" 375case "$SMODE" in 376 "$no_SORT") ;; 377 "$y_SORT") ;; 378 "$Y_SORT") ;; 379 "$m_SORT") ;; 380 "$M_SORT") ;; 381 "$Ym_SORT") ;; 382 "$YM_SORT") ;; 383 *) 384 echo "$PROG: cannot mix -y with -m or -M." >&2 385 echo "$USAGE" >&2 386 exit 1 387 esac 388 389# 390# must have at least one mailbox arg 391# 392if [ "$#" = 0 ]; then 393 echo "$PROG: need to specify one or more mailboxes." >&2 394 echo "$USAGE" >&2 395 exit 1 396 fi 397 398# 399# check that all mailboxes are accessible before starting; 400# also, see if any match files that are zipped; 401# 402ERROR=0 403NEW_MB_LIST= 404IS_NEW_LIST=0 405for MB do 406 if [ ! -f "$MB" ]; then 407 case "$MB" in 408 *'.Z'|*'.gz') 409 ;; 410 *) 411 if [ -f "$MB.Z" ]; then 412 MB="$MB.Z" 413 IS_NEW_LIST=1 414 elif [ -f "$MB.gz" ]; then 415 MB="$MB.gz" 416 IS_NEW_LIST=1 417 fi 418 esac 419 fi 420 421 NEW_MB_LIST=`append_list "$NEW_MB_LIST" "$MB"` 422 423 if [ ! -f "$MB" ]; then 424 echo "$PROG: no such file \"$MB\"." >&2 425 ERROR=1 426 elif [ ! -r "$MB" ]; then 427 echo "$PROG: cannot read \"$MB\"." >&2 428 ERROR=1 429 fi 430 done 431# 432# if the mailbox list has been modified, set the new list to the 433# positional parameter list 434# 435if [ "$ERROR" = 1 ]; then 436 exit 1 437 elif [ "$IS_NEW_LIST" = 1 ]; then 438 set -f 439 _IFS="$IFS" 440 IFS=' 441' 442 set -- $NEW_MB_LIST 443 IFS="$_IFS" 444 set +f 445 fi 446 447echo "$PROG: Begin..." >&2 448 449# 450# make backup dir? 451# 452if [ "$BACKUP" = 1 ]; then 453 if [ ! -d "$BACKUP_DIR" ]; then 454 cmd="mkdir \"$BACKUP_DIR\"" 455 eval "$CMD" || { 456 echo "$PROG: cannot create dir \"$BACKUP_DIR\"." >&2 457 exit 1 458 } 459 fi 460 fi 461 462# 463# make and/or 'cd' WORKDIR? 464# 465if [ "$HERE" = 0 ]; then 466 if [ ! -d "$WORK_DIR" ]; then 467 cmd="mkdir \"$WORK_DIR\"" 468 eval "$CMD" || { 469 echo "$PROG: cannot create dir \"$WORK_DIR\"." >&2 470 exit 1 471 } 472 fi 473 cmd="cd \"$WORK_DIR\"" 474 eval "$CMD" || { 475 echo "$PROG: cannot change to dir \"$WORK_DIR\"." >&2 476 exit 1 477 } 478 fi 479echo "$PROG: working directory is \"`pwd`\"..." >&2 480 481if [ "$CURRENT" = 1 ]; then 482 # 483 # set current date vars C_Y4, C_Y2, C_M2, 484 # for use with CURRENT option 485 # 486 eval `date '+C_Y4="%Y" C_Y2="%y" C_M2="%m"'` 487 fi 488 489 490## 491## each command line mailbox 492## 493for MB do 494# 495 # 496 # MB_DIR and MB_PATH are the relative or absolute path to the 497 # original mailbox; 498 # MB will become the basename of the mbox; 499 # 500 MB_DIR= 501 MB_PATH= 502 # 503 # resolve some mbox path issues 504 # 505 MB_BASE=`basename "$MB"` 506 if [ "./$MB_BASE" = "$MB" ]; then 507 MB="$MB_BASE" 508 fi 509 case "$MB" in 510 /*) 511 # absolute path 512 MB_DIR=`dirname "$MB"` 513 MB_PATH="$MB_DIR/" 514 MB=`basename "$MB"` 515 ;; 516 */*) 517 # relative path 518 MB_DIR="$SRC_PATH"`dirname "$MB"` 519 MB_PATH="$MB_DIR/" 520 MB=`basename "$MB"` 521 ;; 522 *) 523 # initial directory 524 MB_DIR="$SRC_DIR" 525 MB_PATH="$SRC_PATH" 526 esac 527 528 echo " 529$PROG: sorting mailbox \"$MB_PATH$MB\" ..." >&2 530 531 # presumably this has already been checked; 532 # if file is not found, there's definitely a problem... 533 if [ ! -f "$MB_PATH$MB" ]; then 534 echo "$PROG: no such file \"$MB_PATH$MB\"." >&2 535 exit 1 536 fi 537 538 # 539 # make a backup copy? 540 # 541 if [ "$BACKUP" = 1 ]; then 542 echo " 543$PROG: backing up mailbox \"$SRC_DIR/$MB\" ..." >&2 544 # if there's already a copy, move it, don't overwrite 545 rotate_file "$SRC_PATH$BACKUP_DIR/$MB" || { 546 echo "$PROG: cannot rotate file \"$SRC_PATH$BACKUP_DIR/$MB\"." >&2 547 exit 1 548 } 549 550 cmd="cp \"$MB_PATH$MB\" \"$SRC_PATH$BACKUP_DIR\"" 551 eval "$CMD" || { 552 echo "$PROG: cannot copy \"$MB_PATH$MB\" to \"$SRC_PATH$BACKUP_DIR\"." >&2 553 exit 1 554 } 555 fi 556 557 # 558 # get a copy of the source file; 559 # if REMOVE, then just move it here; 560 # 561 if [ "$MB_DIR" != "." ]; then 562 if [ "$REMOVE" = 1 ]; then 563 echo " 564$PROG: moving mailbox \"$MB_PATH$MB\" to working directory ..." >&2 565 cmd="mv \"$MB_PATH$MB\" \"./$MB\"" 566 _STR=move 567 else 568 echo " 569$PROG: copying mailbox \"$MB_PATH$MB\" to working directory ..." >&2 570 cmd="cp \"$MB_PATH$MB\" \"./$MB\"" 571 _STR=copy 572 fi 573 eval "$CMD" || { 574 echo "$PROG: cannot $_STR \"$MB_PATH$MB\" to \"./$MB\"." >&2 575 exit 1 576 } 577 fi 578 579 # 580 # do the decomposition, producing a file for each message in the mbox; 581 # if it's a zipped file, DECOMPOSE can deal with it as is; 582 # 583 echo "" >&2 584 cmd="$DECOMPOSE$PASS_VFLAG \"$MB\"" 585 eval "$CMD" || { 586 echo "$PROG: problem disassembling \"$MB\"." >&2 587 exit 1 588 } 589 590 # 591 # get rid of ./copy, or 592 # get rid of ./orig if REMOVE; 593 # 594 if [ "$MB_DIR" != '.' ]; then 595 echo " 596$PROG: removing working copy of mailbox \"$MB\" ..." >&2 597 cmd="rm \"$MB\"" 598 eval "$CMD" || { 599 echo "$PROG: cannot remove \"$MB\"." >&2 600 exit 1 601 } 602 elif [ "$REMOVE" = 1 -o "$USE_DATES" = 0 ]; then 603 echo " 604$PROG: removing original copy of mailbox \"$MB\" ..." >&2 605 cmd="rm \"$MB\"" 606 eval "$CMD" || { 607 echo "$PROG: cannot remove \"$MB\"." >&2 608 exit 1 609 } 610 fi 611 612 # 613 # do the recomposition, based on options; 614 # if the mbox was a zipped file, RECOMPOSE needs the 615 # non-zipped filename; 616 # 617 echo "" >&2 618 case "$MB" in 619 *'.Z'|*'.gz') 620 # get rid of the suffix 621 _MB=`$AWK <&- 'BEGIN { 622 F = "'"$MB"'"; 623 sub(/((\.Z)|(\.gz))$/,"",F); 624 print F; 625 }'` 626 ;; 627 *) 628 _MB="$MB" 629 esac 630 cmd="$RECOMPOSE$PASS_MFLAG$PASS_YFLAG$PASS_VFLAG \"$_MB\"" 631 eval "$CMD" || { 632 echo "$PROG: problem reassembling \"$_MB\"." >&2 633 exit 1 634 } 635 636 # 637 # if none of the date flags used, only do this part; 638 # the logic here is a little convoluted -- if you can think 639 # of anything that makes more sense, let me know; 640 # 641 if [ "$USE_DATES" = 0 ]; then 642 # 643 # if REMOVE or 644 # if we're working in the directory of the original mbox, 645 # and if the original file was zipped, then re-zip it; 646 # 647 if [ "$REMOVE" = 1 -o "$MB_DIR" = '.' ]; then 648 case "$MB" in 649 *'.Z') 650 cmd="compress \"$_MB\"" 651 eval "$CMD" || { 652 echo "$PROG: cannot compress \"$_MB\"." >&2 653 exit 1 654 } 655 ;; 656 *'.gz') 657 cmd="gzip \"$_MB\"" 658 eval "$CMD" || { 659 echo "$PROG: cannot gzip \"$_MB\"." >&2 660 exit 1 661 } 662 esac 663 else 664 MB="$_MB" # don't want the suffix (if there is one) 665 fi 666 if [ "$REMOVE" = 1 -a "$MB_DIR" != '.' ]; then 667 cmd="mv \"$MB\" \"$MB_DIR\"" 668 eval "$CMD" || { 669 echo "$PROG: cannot move \"$MB\" to \"$MB_DIR\"." >&2 670 exit 1 671 } 672 fi 673 674 continue 675 fi 676 677 # 678 # from this point on, we're concerned with moving the various 679 # merged mailboxes to where they need to go, ie, any of: 680 # SRC_DIR/mbox.YYMM 681 # SRC_DIR/YYMM/mbox 682 # SRC_DIR/mbox.YYYY 683 # SRC_DIR/YYYY/mbox 684 # SRC_DIR/YYYY/mbox.MM 685 # SRC_DIR/YYYY/MM/mbox 686 # SRC_DIR/mbox (CURRENT) 687 # 688 689 REDO_LIST= # mboxes to redo (ie, after appending, sort/merge again) 690 COMPRESS_LIST= # mboxes to re-compress 691 GZIP_LIST= # mboxes to re-gzip 692 MB="$_MB" # don't want any zip suffix any more (if there was one) 693 694 # 695 # only want to do this (move files and recurse) if not HERE 696 # 697 if [ "$SRC_DIR" != '.' ]; then 698# # 699 # 700 # get list of [path/]files that were generated; 701 # make them into the positional parameters; 702 # unfortunately, we do not get this info from RECOMPOSEMAIL; 703 # 704 DFILES= 705 case "$SMODE" in 706 $m_SORT|$y_SORT) 707 DFILES=`ls -d "$MB".[0-9][0-9][0-9][0-9]` 708 ;; 709 $M_SORT|$Y_SORT) 710 DFILES=`ls -d [0-9][0-9][0-9][0-9]/"$MB"` 711 ;; 712 $Ym_SORT) 713 DFILES=`ls -d [0-9][0-9][0-9][0-9]/"$MB".[0-1][0-9]` 714 ;; 715 $YM_SORT) 716 DFILES=`ls -d [0-9][0-9][0-9][0-9]/[0-1][0-9]/"$MB"` 717 esac 718 set -f 719 _IFS="$IFS" 720 IFS=' 721' 722 set -- X $DFILES 723 shift 724 IFS="$_IFS" 725 set +f 726 727 for DFILE do 728# # # 729 echo "" >&2 730 731 # 732 # decompose the [path/]mbox name, based on sort mode; 733 # this info will be needed for moves and such; 734 # 735 736 DDIR= SUFX= # dir and/or suffix 737 B_SUFX= # for backup filenames 738 739 case "$SMODE" in 740 "$y_SORT") # mbox.yyyy 741 eval `$AWK <&- 'BEGIN { 742 DF = "'"$DFILE"'"; 743 N = split(DF,A,"\."); 744 print "SUFX=\"" A[N] "\""; 745 print "B_SUFX=\"" A[N] "\""; 746 }'` 747 ;; 748 "$Y_SORT") # yyyy/mbox 749 eval `$AWK <&- 'BEGIN { 750 DF = "'"$DFILE"'"; 751 N = split(DF,A,"/"); 752 print "DDIR=\"" A[1] "\""; 753 print "B_SUFX=\"" A[1] "\""; 754 }'` 755 ;; 756 "$m_SORT") # mbox.yymm 757 eval `$AWK <&- 'BEGIN { 758 DF = "'"$DFILE"'"; 759 N = split(DF,A,"\."); 760 print "SUFX=\"" A[N] "\""; 761 print "B_SUFX=\"" A[N] "\""; 762 }'` 763 ;; 764 "$M_SORT") # yymm/mbox 765 eval `$AWK <&- 'BEGIN { 766 DF = "'"$DFILE"'"; 767 N = split(DF,A,"/"); 768 print "DDIR=\"" A[1] "\""; 769 print "B_SUFX=\"" A[1] "\""; 770 }'` 771 ;; 772 "$Ym_SORT") # yyyy/mbox.mm 773 eval `$AWK <&- 'BEGIN { 774 DF = "'"$DFILE"'"; 775 N = split(DF,A,"/"); 776 N2 = split(A[2],A2,"\."); 777 print "DDIR=\"" A[1] "\""; 778 print "SUFX=\"" A2[N2] "\""; 779 print "B_SUFX=\"" substr(A[1],3) A2[N2] "\""; 780 }'` 781 ;; 782 "$YM_SORT") # yyyy/mm/mbox 783 DDIR="$_MF_Y4/$_MF_M2" 784 eval `$AWK <&- 'BEGIN { 785 DF = "'"$DFILE"'"; 786 N = split(DF,A,"/"); 787 print "DDIR=\"" A[1] "/" A[2] "\""; 788 print "B_SUFX=\"" substr(A[1],3) A[2] "\""; 789 }'` 790 esac 791 792 # 793 # will the existing file need to be unzipped? 794 # 795 if [ -f "$SRC_PATH$DFILE" ]; then 796# # # # 797 [ "$RECURSE" = 1 ] && 798 REDO_LIST=`append_list "$REDO_LIST" "$DFILE"` 799 elif [ -f "$SRC_PATH$DFILE.Z" ]; then 800 cmd="uncompress \"$SRC_PATH$DFILE\"" 801 if eval "$CMD" 802 then 803 COMPRESS_LIST=`append_list "$COMPRESS_LIST" "$DFILE"` 804 REDO_LIST=`append_list "$REDO_LIST" "$DFILE"` 805 else 806 echo "$PROG: cannot uncompress \"$SRC_PATH$DFILE\"." >&2 807 exit 1 808 fi 809 elif [ -f "$SRC_PATH$DFILE.gz" ]; then 810 cmd="gunzip \"$SRC_PATH$DFILE\"" 811 if eval "$CMD" 812 then 813 GZIP_LIST=`append_list "$GZIP_LIST" "$DFILE"` 814 REDO_LIST=`append_list "$REDO_LIST" "$DFILE"` 815 else 816 echo "$PROG: cannot gunzip \"$SRC_PATH$DFILE\"." >&2 817 exit 1 818 fi 819 fi 820 821 # 822 # move or append to the source location 823 # 824 if [ -f "$SRC_PATH$DFILE" ]; then 825# # # # 826 # backup any file already there 827 if [ "$BACKUP" = 1 ]; then 828 # if there's already a copy, move it, don't overwrite 829 rotate_file "$SRC_PATH$BACKUP_DIR/$MB.$B_SUFX" || { 830 echo "$PROG: cannot rotate file \"$SRC_PATH$BACKUP_DIR/$MB.$B_SUFX\"." >&2 831 exit 1 832 } 833 cmd="cp \"$SRC_PATH$DFILE\" \"$SRC_PATH$BACKUP_DIR/$MB.$B_SUFX\"" 834 eval "$CMD" || { 835 echo "$PROG: cannot copy \"$SRC_PATH$DFILE\" to \"$SRC_PATH$BACKUP_DIR/$MB.$B_SUFX\"." >&2 836 exit 1 837 } 838 fi && 839 # 840 # append to the existing file 841 # 842 { 843 cmd="cat \"$DFILE\" >> \"$SRC_PATH$DFILE\"" 844 eval "$CMD" || { 845 echo "$PROG: cannot append \"$DFILE\" to \"$SRC_PATH$DFILE\"." >&2 846 exit 1 847 } 848 } && 849 { 850 cmd="rm \"$DFILE\"" 851 eval "$CMD" || { 852 echo "$PROG: cannot remove \"$DFILE\"." >&2 853 exit 1 854 } 855 } 856 # 857 # if no original 858 # 859 else 860# # # # 861 # 862 # need to create the directory? 863 # 864 if [ "$USE_DIRS" = 1 -a ! -d "$SRC_PATH$DDIR" ]; then 865# # # # # 866 cmd="mkdir -p \"$SRC_PATH$DDIR\"" 867 eval "$CMD" || { 868 echo "$PROG: cannot mkdir \"$SRC_PATH$DDIR\"." >&2 869 exit 1 870 } 871 fi 872# # # # # 873 # 874 # new file moves to new dir 875 # 876 cmd="mv \"$DFILE\" \"$SRC_PATH$DFILE\"" 877 eval "$CMD" || { 878 echo "$PROG: cannot move \"$DFILE\" to \"$SRC_PATH$DFILE\"." >&2 879 exit 1 880 } 881 fi 882# # # # 883 done 884# # # 885 886 # 887 # a little message from RECURSE... 888 # 889 if [ "$RECURSE" = 1 ]; then 890# # # 891 if [ "$REDO_LIST" = '' ]; then 892# # # # 893 echo " 894$PROG: nothing to recurse..." >&2 895 else 896 897 _STR=`echo $REDO_LIST` 898 echo " 899$PROG: recursing $_STR ..." >&2 900 fi 901 fi 902 903 if [ \( "$RECURSE" = 1 -a -n "$REDO_LIST" \) -o -n "$COMPRESS_LIST" -o -n "$GZIP_LIST" ]; then 904# # # 905 906 # if RECURSE, redo any mailboxes that have been 907 # appended to; also recompress any that were 908 # decompressed; 909 set -f 910 _IFS="$IFS" 911 IFS=' 912' 913 set -- X $REDO_LIST 914 shift 915 IFS="$_IFS" 916 set +f 917 918 for RFILE do 919# # # # 920 if [ "$RECURSE" = 1 ]; then 921# # # # # 922 echo "" >&2 923 echo "$PROG: recursing \"$RFILE\"..." >&2 924 925 # 926 # REDO_LIST consists of 927 # [path/]mbox[.sufx] 928 # entries; 929 # 930 # decompose the entries, 931 # based on sort mode 932 # 933 RDIR= RSUF= 934 935 case "$SMODE" in 936 "$y_SORT") # mbox.yyyy 937 eval `$AWK <&- 'BEGIN { 938 DF = "'"$DFILE"'"; 939 N = split(DF,A,"\."); 940 print "RSUF=\"" A[N] "\""; 941 }'` 942 ;; 943 "$Y_SORT") # yyyy/mbox 944 eval `$AWK <&- 'BEGIN { 945 DF = "'"$DFILE"'"; 946 N = split(DF,A,"/"); 947 print "RDIR=\"" A[1] "\""; 948 }'` 949 ;; 950 "$m_SORT") # mbox.yymm 951 eval `$AWK <&- 'BEGIN { 952 DF = "'"$DFILE"'"; 953 N = split(DF,A,"\."); 954 print "RSUF=\"" A[N] "\""; 955 }'` 956 ;; 957 "$M_SORT") # yymm/mbox 958 eval `$AWK <&- 'BEGIN { 959 DF = "'"$DFILE"'"; 960 N = split(DF,A,"/"); 961 print "RDIR=\"" A[1] "\""; 962 }'` 963 ;; 964 "$Ym_SORT") # yyyy/mbox.mm 965 eval `$AWK <&- 'BEGIN { 966 DF = "'"$DFILE"'"; 967 N = split(DF,A,"/"); 968 N2 = split(A[2],A2,"\."); 969 print "RDIR=\"" A[1] "\""; 970 print "RSUF=\"" A2[N2] "\""; 971 }'` 972 ;; 973 "$YM_SORT") # yyyy/mm/mbox 974 DDIR="$_MF_Y4/$_MF_M2" 975 eval `$AWK <&- 'BEGIN { 976 DF = "'"$DFILE"'"; 977 N = split(DF,A,"/"); 978 print "RDIR=\"" A[1] "/" A[2] "\""; 979 }'` 980 esac 981 982 # move the file to recurse here 983 cmd="mv \"$SRC_PATH$RFILE\" \"./$MB\"" 984 eval "$CMD" || { 985 echo "$PROG: cannot move \"$SRC_PATH$RFILE\" to \"./$MB\"." >&2 986 exit 1 987 } 988 989 # sort/merge it, no backup; 990 # no additional recursing should be necessary; 991 # should all be for the same month or year; 992 993 # decompose the mbox 994 echo "" >&2 995 cmd="$DECOMPOSE$PASS_VFLAG \"$MB\"" 996 eval "$CMD" || { 997 echo "$PROG: problem disassembling \"$MB\"." >&2 998 exit 1 999 } 1000 1001 # remove the mbox 1002 cmd="rm \"$MB\"" 1003 eval "$CMD" || { 1004 echo "$PROG: cannot remove \"$MB\"." >&2 1005 exit 1 1006 } 1007 1008 # recompose the mbox; 1009 # probably dont really need the date 1010 # flags... 1011 echo "" >&2 1012 cmd="$RECOMPOSE$PASS_MFLAG$PASS_YFLAG$PASS_VFLAG \"$MB\"" 1013 eval "$CMD" || { 1014 echo "$PROG: problem reassembling \"$MB\"." >&2 1015 exit 1 1016 } 1017 1018 # move the sorted mbox to its final location 1019 echo "" >&2 1020 cmd="mv \"$RFILE\" \"$SRC_DIR/$RFILE\"" 1021 eval "$CMD" || { 1022 echo "$PROG: cannot move \"$RFILE\" to \"$SRC_DIR/$RFILE\"." >&2 1023 exit 1 1024 } 1025 fi 1026# # # # # 1027 1028 # 1029 # if the orig file 1030 # was compressed or gzipped, then 1031 # restore it thusly 1032 # 1033 case " 1034$COMPRESS_LIST 1035" in 1036# # # # # 1037 *" 1038$RFILE 1039"*) 1040 cmd="compress \"$SRC_DIR/$RFILE\"" 1041 eval "$CMD" || { 1042 echo "$PROG: cannot compress \"$SRC_DIR/$RFILE\"." >&2 1043 exit 1 1044 } 1045 ;; 1046 *) 1047 case " 1048$GZIP_LIST 1049" in 1050 *" 1051$RFILE 1052"*) 1053 cmd="gzip \"$SRC_DIR/$RFILE\"" 1054 eval "$CMD" || { 1055 echo "$PROG: cannot gzip \"$SRC_DIR/$RFILE\"." >&2 1056 exit 1 1057 } 1058 ;; 1059 *) 1060 esac 1061 esac 1062# # # # # 1063 done 1064# # # # 1065 fi 1066# # # 1067 fi 1068# # 1069 1070 # 1071 # if CURRENT, move current month mbox back to SRC_DIR 1072 # 1073 if [ "$CURRENT" = 1 ]; then 1074# # 1075 DDIR= DDIR_= 1076 SUFX= _SUFX= 1077 1078 case "$SMODE" in 1079 "$y_SORT") 1080 SUFX="$C_Y4" 1081 ;; 1082 "$Y_SORT") 1083 DDIR="$C_Y4" 1084 ;; 1085 "$m_SORT") 1086 SUFX="$C_Y2$C_M2" 1087 ;; 1088 "$M_SORT") 1089 DDIR="$C_Y2$C_M2" 1090 ;; 1091 "$Ym_SORT") 1092 DDIR="$C_Y4" 1093 SUFX="$C_M2" 1094 ;; 1095 "$YM_SORT") 1096 DDIR="$C_Y4/$C_M2" 1097 esac 1098 1099 DDIR_="${DDIR:+$DDIR/}" 1100 _SUFX="${SUFX:+.$SUFX}" 1101 1102 CFILE="$DDIR_$MB$_SUFX" 1103 1104 if [ -f "$SRC_PATH$CFILE" ]; then 1105# # # 1106 cmd="mv \"$SRC_PATH$CFILE\" \"$MB_PATH$MB\"" 1107 eval "$CMD" || { 1108 echo "$PROG: cannot move \"$SRC_PATH$CFILE\" to \"$MB_PATH$MB\"." >&2 1109 exit 1 1110 } 1111 1112 # 1113 # if CURRENT and orig mbox is now non-existent, 1114 # make an empty one 1115 # 1116 elif [ ! -f "$MB_PATH$MB" ]; then 1117 echo "" >&2 1118 cmd="> \"$MB_PATH$MB\"" 1119 eval "$CMD" || { 1120 echo "$PROG: cannot create file \"$MB_PATH$MB\"." >&2 1121 exit 1 1122 } 1123 fi 1124# # # 1125 fi 1126# # 1127 done 1128# 1129 1130echo " 1131$PROG: done. 1132" >&2 1133 1134exit 1135