[comp.unix.questions] Sorting mail files chronologically on Unix

Leisner.henr801c@xerox.com (04/25/91)

I'm writing a program to convert mail files from one format (on one system) to
another.

The source mail file file has mail notes in a  well-defined format, which are
not necessarily sorted chronologically.

There is a sort command (in the mail tool) on the source system, which sorts a
table of contents file chronologically.  The mail file is untouched.

How do I sort a mailfile chronologically on Unix?  I looked in the
documentation for Mail (the man pages) and saw nothing about sorting.  Figured
this is useful and someone already did this...

(BTW -- is there an Xwindows tool to read Unix mail files and does it have the
source code to decode the mail file?  What is it called?  (I'm not a big
Xwindows user yet).

marty
(Knowledge is useful in the Information Age)
(Software is mindstuff.  It is the hardest activity created by man)

ARPA:	leisner.henr801c@xerox.com
NS:  leisner:henr801c:xerox
UUCP:	hplabs!arisia!leisner

itkin@mrspoc.Transact.COM (Steven M. List) (04/30/91)

Leisner.henr801c@xerox.com writes:

>I'm writing a program to convert mail files from one format (on one system) to
>another.
>
>The source mail file file has mail notes in a  well-defined format, which are
>not necessarily sorted chronologically.
>
>There is a sort command (in the mail tool) on the source system, which sorts a
>table of contents file chronologically.  The mail file is untouched.
>
>How do I sort a mailfile chronologically on Unix?  I looked in the
>documentation for Mail (the man pages) and saw nothing about sorting.  Figured
>this is useful and someone already did this...

The way that Elm allows you to do this is in a couple of steps:

    1.  Sort the "table of contents" in whatever order you want it
    2.  Tag all the messages
    3.  Save all tagged messages to an alternate file
    4.  Replace the original mail folder with the alternate

Since Elm saves messages in the same order in which they're displayed in the
"table of contents", you have the flexibility to order them whatever way
you wish.

Borrowing from this approach, you need only create an index of the messages
including whatever information you might wish to sort on, sort that index,
and then use the position information (which you also saved) to write out
the messages in the order in which they're sorted.  Note that you still
need to create an intermediate, temporary file to write the sorted
messages to before overwriting the original folder.

If someone actually goes to the trouble to develop such a program, I'm
sure that they'd find a large number of people who'd be interested in it.
It'd be particularly useful when retrieving multipart uuencoded files in
putting them in the right order!
-- 
 +----------------------------------------------------------------------------+
 :                Steven List @ Transact Software, Inc. :^>~                  :
 :           Chairman, Unify User Group of Northern California                :
 :                         itkin@Transact.COM                                 :

oz@yunexus.yorku.ca (Ozan Yigit) (05/02/91)

steven@Transact.COM writes:

>If someone actually goes to the trouble to develop such a program, I'm
>sure that they'd find a large number of people who'd be interested in it.

It is called mh.One can unpack the mail file into a folder with inc, use
sortm on the folder to chronologically sort the message files within the
folder, and repack the these message files into a single file, if that's
what is needed.

oz

dattier@vpnet.chi.il.us (David W. Tamkin) (05/02/91)

steven@Transact.COM wrote in <1991Apr29.204812.3476@mrspoc.Transact.COM>:

| Leisner.henr801c@xerox.com writes:

| >How do I sort a mailfile chronologically on Unix?  I looked in the
| >documentation for Mail (the man pages) and saw nothing about sorting. 
| >Figured this is useful and someone already did this...

| The way that Elm allows you to do this is in a couple of steps:

|     1.  Sort the "table of contents" in whatever order you want it
|     2.  Tag all the messages
|     3.  Save all tagged messages to an alternate file
|     4.  Replace the original mail folder with the alternate

| Note that you still
| need to create an intermediate, temporary file to write the sorted
| messages to before overwriting the original folder.

No, you don't have to create an intermediate mail folder.  You can use Elm
to sort by any key (and forward or reverse) as you wish, tag all messages in
the folder, and save [which will work on all tagged messages if any are
tagged] to the very same folder.

Elm will append copies of them in the current display order to the end of the
file and mark the originals for deletion.  Then resynchronize with '$' and
the originals are removed, leaving the copies in the desired order.

This method works with both Elm 2.2 and Elm 2.3.

David Tamkin  PO Box 7002  Des Plaines IL  60018-7002  dattier@vpnet.chi.il.us
GEnie:D.W.TAMKIN  CIS:73720,1570  MCIMail:426-1818  708 518 6769  312 693 0591

"Parker Lewis Can't Lose" mailing list:
 flamingo-request@esd.sgi.com (relay)  flamingo-request@ddsw1.mcs.com (digest)

nelson@berlioz.nsc.com (Taed Nelson) (05/02/91)

>>If someone actually goes to the trouble to develop such a program, I'm
>>sure that they'd find a large number of people who'd be interested in it.

Some kind soul sent me this script a while back when I asked the same
question.  If the name is not in the comments, then I don't know who wrote
it.  It is included below.

It is followed by an AWK script which I wrote (borrowing from the
aformentioned program) to delete any pieces of mail which have a Subject which
starts with the character `@'.  The reason I have this is because I save all
of my outgoing mail in a record, but sometimes I send out junk that I don't
want wasting space in my record.  By putting an `@', I allow that mail to be
deleted when I run the script under AWK.

SORT MAIL:
------------------------------------------------------------------------------
#!/bin/sh
#
# sort mail in a folder chronologically
#
# From unido!uunet!amdahl!rtech!llama!daveb Thu Jan 28 09:00:34 1988
# Received: by fb10vax.sbsvax.uucp; Thu, 28 Jan 88 09:00:32 +0100 (MET)
# Date: Wed, 27 Jan 88 16:54:52 pst
# From: unido!uunet!amdahl!rtech!llama!daveb (Dave Brower)

new=sorted.$$

myname=`basename $0`
case $MAILSORT in	# assume MAILSORT is an env. variable
  -v)
	RMFLAG='-i'
	;;
  *)
	RMFLAG='-f'
	trap 'rm -f $new ; exit' 0 1 2 3 5 9
	;;
esac

case $# in
  '')
	echo -n "Name the mail folder to sort: "
	read old
	;;
  1)
	old=$1
	;;
  *)
	echo "Usage: $myname old"
	exit
	;;
esac

if [ ! -f $old ]
  then
	echo "$old: no such file"
	exit
elif [ ! -w $old ]
  then
	echo "$old: no write access"
	exit
fi


awk '

BEGIN {
	month["Jan"] = 1
	month["Feb"] = 2
	month["Mar"] = 3
	month["Apr"] = 4
	month["May"] = 5
	month["Jun"] = 6
	month["Jul"] = 7
	month["Aug"] = 8
	month["Sep"] = 9
	month["Oct"] = 10
	month["Nov"] = 11
	month["Dec"] = 12
}

/^From / {

    ++msg

    if( NF == 7)
	hold = sprintf("%s:%02d:%02d:%s %d", $7, month[$4], $5, $6, msg)

#    if( getline && NF == 7 && $1 == "Date:")
#        hold = sprintf( "19%s:%02d:%02d:%s %d", $5, month[$4], $3, $6, msg)

    print hold
}

' $old | sort -n |  sed "s/.* \(.*\)/s \1 $new/" | mail -f $old > /dev/null

if [ $? = 0 ]
then
	mv $RMFLAG $new $old
	echo "$old is now sorted"
else
	echo "Problems sorting $old, left untouched"
fi

------------------------------------------------------------------------------




KILL MAIL:
------------------------------------------------------------------------------
# The AWK script which deletes all mail on stdin with the first subject
#   character as `@'.
# Written April 1991 by Taed Nelson (nelson@desktop.nsc.com)

# Place the message or the packet record in the appropriate file.
function sortMessage() {
	if ((saveMode != KILL) && (saveMode != NONE)) {
		# Don't use "i in messageStore" since it doesn't keep the order
		# Also, get rid of trailing blanks since I hate them
		for (i=1; i <= (numLines - trailingBlanks); i++) {
			print messageStore[i];
			delete messageStore[i];
		}

		# Make sure there's a newline between the records
		printf ("\n");
	}
}


BEGIN {
	numLines = 0;

	NONE = 0;
	KILL = 1;
	MESSAGE = 2;
	UNKNOWN = 3;

	# So that we don't have any output if there are only kill messages
	saveMode = NONE;
}


# The "From" line contains the date we received the message.
# It better be the first line, or it's going to get confused.
($1 == "From") && (NF == 7) {
	sortMessage();

	saveMode = UNKNOWN;
	numLines = 0;
	++messageNum;
}


# If we know we're collecting a kill or the whitespace between messages,
#   we can skip to the next message.
(saveMode == KILL) || (saveMode == NONE) {
	next;
}


# Always collect the text of the messages.
{
	messageStore[++numLines] = $0;

	if ((saveMode == UNKNOWN) && ($1 ~ /^Subject:$/)) {
		if ($2 ~ /^\@/) {
			saveMode = KILL;
		}
		else {
			saveMode = MESSAGE;
		}
	}

	if ($0 ~ /^$/) {
		trailingBlanks++;
	}
	else {
		trailingBlanks= 0;
	}
}


# Don't forget to sort the last message!
END {
	sortMessage();
}