On Fri, Dec 21, 2001 at 10:36:45AM -0800, Gary Funck wrote:
I have a fair number of maildir folders of archived mail that I would
like to sort on a monthly basis.
This is likely not a problem to be handled with procmail, but one that
is more easily handled with formail, and other tools. I needed to solve
a similar problem a while ago, and came up with this solution:
http://www.rosat.mpe-garching.mpg.de/mailing-lists/procmail/1997-02/msg0
0178.html
I developed a simple program called 'mdate', which takes a date in free
form, and tries to convert it into a canonical form. This, combined with
"formail" as the tool of choice for extracting the Date: header
information should get you what you need.
<snip>
Here's a shell script that accepts a list of file names as arguments,
and that uses formail and the mdate utility to extract the date field
from each file (which is presumed to be a single mail message), and to
then copy the file into a directory named as YEAR/MONTH in CCYY/MM
format. If you want to use month names or some other encoding, the
scipt will need to be modified.
Gary,
Your solution worked very well, indeed. I noted the following problems on my
platform ( Red Hat Linux 7.1, glibc-2.2.4-19) :
- mdate uses 'cftime()' to format the output date. The corresponding
function for me is strftime().
- GNU touch uses a different time format.
I modified mdate (three cheers for open source! :-)) to use strftime() and
output dates with a runtime definable format. Use mdate -f or mdate --format
for this. I've included the diff.
I also modified your shell script to process and output the maildir format.
I have included the script and the diff ... hope this is acceptable on this
list.
Thanks a ton for the solution and I hope my diffs are useful.
-- Biju
---8<--cut here-----
#!/bin/bash
#
# sortmaildir : sorts Maildir files on the basis of date and dumps into
# new maildirs
#
#
for i in $*; do
if [ -d $i ]; then
if [ -d $i/cur ] && [ -d $i/new ] && [ -d $i/tmp ]; then
for curdir in cur new tmp; do
for file in $i/$curdir/*; do
filename=`echo $file | sed -e "s/$i\/$curdir\///"`
if d=`formail -x Date: < $file` ; then
if m=`./mdate $d` ; then
Y=`echo $m | sed -e 's/^........//'`
M=`echo $m | sed -e 's/..........$//'`
parent_dir="$i-$Y/$M"
if [ ! -d $parent_dir ] ; then
mkdir -p $parent_dir/cur
mkdir -p $parent_dir/new
mkdir -p $parent_dir/tmp
fi
dir="$i-$Y/$M/$curdir"
if [ ! -d $dir ] ; then
mkdir -p $dir
fi
cp $file $dir
f='%Y%m%d%H%M'
touch -t `./mdate -f$f $d` $dir/$filename
echo "$i: copied to $dir/$filename"
else
echo "Unable to parse date: $d -> $m"
if [ ! -d $i-unsorted ] ; then
mkdir -p $i-unsorted/cur
mkdir -p $i-unsorted/new
mkdir -p $i-unsorted/tmp
fi
dir="$i-unsorted/$curdir"
if [ ! -d $dir ] ; then
mkdir -p $dir
fi
cp $file $dir
echo "$i: copied to $dir/$filename"
fi
else
echo "No Date in mail"
if [ ! -d $i-unsorted ] ; then
mkdir -p $i-unsorted/cur
mkdir -p $i-unsorted/new
mkdir -p $i-unsorted/tmp
fi
dir="$i-unsorted/$curdir"
if [ ! -d $dir ] ; then
mkdir -p $dir
fi
cp $file $dir
f='%Y%m%d%H%M'
echo "$i: copied to $dir/$filename"
fi
done
done
fi
fi
done
---8<--cut here-----
--- ../mdate/mdate.y Sat Dec 22 09:42:38 2001
+++ mdate.y Sat Dec 22 15:49:35 2001
@@ -836,26 +836,72 @@
{
}
-main(argc, argv)
-int argc;
-char *argv[];
+
+#include <getopt.h>
+
+int main(int argc, char *argv[])
{
+ static struct option long_options[] = {
+ {"format", required_argument, 0, 'f'}
+ };
+ int option_index = 0;
+ int c;
+ char format_string[32] = "";
+ char dbuf[1024] = "";
+ char mbuf[1024] = "";
time_t t;
- int i;
- char dbuf[1024];
- char mbuf[1024];
- if (argc <= 1) exit(0);
- strcpy(dbuf, argv[1]);
- for (i = 2; i < argc; ++i) {
- strcat(dbuf, " ");
- strcat(dbuf, argv[i]);
+
+ if (argc <= 1)
+ exit(1);
+
+ opterr=0;
+ do {
+ c = getopt_long(argc, argv, "f:", long_options, &option_index);
+ switch (c) {
+ case 'f':
+ strcpy(format_string, optarg);
+ break;
+ /*
+ * add more options here
+ */
+ case -1:
+ default:
+ /*
+ * do nothing
+ */
+ }
+ }
+ while (c != -1);
+
+ if (optind < argc) {
+ while (optind < argc) {
+ strcat(dbuf, argv[optind++]);
+ strcat(dbuf, " ");
+ }
}
+
t = mdate(dbuf);
if (t < 0) {
fprintf(stderr, "%s: invalid date: '%s'\n", argv[0], dbuf);
exit(2);
}
- cftime(mbuf, "%m%d%H%M%Y", &t);
+
+ /*
+ * If there is no format spec then output the default.
+ * otherwise output according to the spec.
+ *
+ */
+ if (strlen(format_string) > 0) {
+ /*
+ * use format spec: DOES NOT CHECK VALIDITY
+ */
+ strftime(mbuf, 1024, format_string, localtime(&t));
+ } else {
+ strftime(mbuf, 1024, "%m%d%H%M%Y", localtime(&t));
+ }
+
puts(mbuf);
+
exit(0);
+
}
--
-------------------------------------------------
Biju Chacko | biju(_at_)exocore(_dot_)com (work)
Exocore Consulting | biju_chacko(_at_)yahoo(_dot_)com (play)
Bangalore, India | http://www.exocore.com
-------------------------------------------------
The chief enemy of creativity is "good" sense
-- Picasso
_______________________________________________
procmail mailing list
procmail(_at_)lists(_dot_)RWTH-Aachen(_dot_)DE
http://MailMan.RWTH-Aachen.DE/mailman/listinfo/procmail