procmail
[Top] [All Lists]

Re: expiring SPAM in Maildirs?

2008-07-30 11:56:35
At 20:17 2008-07-29 +0100, N.J. Mann wrote:

find /path/to/search -type f ! -mnewer /path/to/reference/file

It should be noted that there are differences between gnu and bsd tools -- for instance, mnewer isn't in gnu. It's just -newer (which is what the bsd manpage says -mnewer is a synonym for -- so may as well juse use -newer for better compatability).

Likewise, 'date' in gnu has the -r parameter which works with a _file_ to get the reference time (just the modification time, not ctime or atime) - handy, but different than bsd, which has a -r for reference time as well - but takes a date, including an epoch timecode (which, in terms of the date utility, is more appropriate). If the two met in the middle, it'd be nice, esp with the bsd -v parm - we'd be there.

> find /path/to/.SPAM/ -type f -ctime +30 -exec rm {} \;
>
> to expire the spam that is 30 days old
>
> something like
>
> find /path/to/.SPAM -type f -newercc +30 /path/to/cur -ls
>
> but -newerXY doesn't appear to take a modifier like +30

The beauty of shell expansion is that you can use the same basic syntax in invocation, but expand the results of ANOTHER command. A perl script to get the date of a reference file, subtract some number of days from that and return the value (say, as MINUTES) on stdout would do the trick nicely, like so:

        find /path/to/.SPAM -type f -mmin +`olderthan /path/to/cur 30` -ls

(yea, I'm specifying age in days, but using -mmin - it's how I churned out the perlscript - take days for convenience, but for some semblance of precision, emit minutes)

Alternately, you could create a temporary file and stamp it with a modified date, using a perl script not unlike olderthan above - same two arguments, but emits the name of the tempfile it created with the magical datestamp, so you can use it in the find operation (or whatever) and subsequently remove it. This would be able to create a timestamp EXACTLY as needed, and your find operation would be a standard invocation.

I've included the perlscript source for olderthan below. One could expand upon it to report epoch timestamp, emit days vs. minutes, or whatever.

Note that find will bail complaining about invalid argument if the expanded script output fails - either becuase the olderthan isn't available, or because it terminated abnormally (issuing an error message instead of a numeric), so failure is at least not catastrophic (such as matching all files and deleting your entire mailspool <g>).

ref_date=$(date -v-30d -jf '%s' `stat -f %m /path/to/reference/file` '+%s')
ref_date=$((ref_date / 86400))

This will of course give you a rounded ('floor') integer result for days. That's probably "close enough", but the loss of precision should be noted - it can be _nearly_ an entire day. It is why I chose to use minutes above...

find /path/to/search -type f -mtime ${ref_date}d

I'm going to guess you're running FreeBSD or a close relative. stat isn't on my gnu or non-freebsd systems as a program - it's a standard C library function. gnu date doesn't support the syntax you're using there either.


#!/usr/local/bin/perl -w
#
# olderthan
#
# 20080730/1132 SBS     Created
#

use strict;
use warnings;

MAIN:
{
        # process:
        # take first argument from commandline, stat it, convert to epoch
        # take second argument, multiply by seconds in a day
        # subtract from stat'd time to establish source date
        # subtract this figure from the current time to get an age
        # emit value expressed in integer minutes.

        die "Usage\n$0 referencefile days\n"
                if (@ARGV < 2);

        my $referencefile = $ARGV[0];
        my $referencetime = $ARGV[1];
        my ($oldtime, $nowtime, $stattime);

        die "$referencefile doesn't exist\n"
                unless -e $referencefile;

        ($stattime) = (stat $referencefile)[9];

        $oldtime = $stattime - ( $referencetime * 60 * 60 * 24 );

        # okay, now get the current time since epoch
        $nowtime = time();

        # age is $nowtime minus $oldtime
        # express it in minutes to stdout
        print( int ( ( $nowtime - $oldtime ) / 60 ) );

#   Done.
}

-Sean ( in favour of using the right tools to get the jobber done ) Straw

---
 Sean B. Straw / Professional Software Engineering

 Procmail disclaimer: <http://www.professional.org/procmail/disclaimer.html>
 Please DO NOT carbon me on list replies.  I'll get my copy from the list.

____________________________________________________________
procmail mailing list   Procmail homepage: http://www.procmail.org/
procmail(_at_)lists(_dot_)RWTH-Aachen(_dot_)DE
http://MailMan.RWTH-Aachen.DE/mailman/listinfo/procmail

<Prev in Thread] Current Thread [Next in Thread>