One of the fun situations you find yourself in when administrating people’s email (at least, I find myself in this situation frequently enough, and I am an uninteresting person, so this is what passes for a fun situation in my world) is the dreaded I-have-magically-hit-my-email-quota problem. The conversation usually runs something like this:

User: HALP I cannot send any email on this address!

Me: checks logs The mail logs are telling me that it can’t write to file due to quota issues. Looks like you’ve hit your $BIGNUM quota.

User: I don’t know why the system quota is saying I have $BIGNUM of mail when $MAILCLIENT informs me I have $MUCHSMALLERNUM of mail.

Me: cd’s into user’s maildir directory, starts running ll -ah like a boss

User: I mean, holy crap, I friggin’ hate email, why does the world have to hate me, I have $VERYIMPORTANTATTACHMENT to send to $BIGCLIENT and then this happens. Why don’t computers run on happiness and unicorn farts?

Me: Ah, it looks like this email address has $BIGNUM – $MUCHSMALLERNUM worth of mail in its .spam directory.

User: I have a dot spam directory? How come I can’t see it in $MAILCLIENT?

Me: You know, I could explain the concept of how hidden directories work in linux, and bemoan the fact that the mailserver uses them and most mail clients don’t, but in lieu of that, how about I delete all of that spam for you, thereby fixing your quota issue?

User: in a monotone Thank you sir may I have another

Here is the bash one-liner for removing the mails from this directory:

for file in $(find -type f -maxdepth 1); do rm -fv $file; done

“But sir! Sir!” you find yourself saying, “why on earth are you not using xargs? Surely piping find’s output to xargs is more memory-efficient than a naive for loop!”

While it is true that a for loop is less memory efficient than piping find to xargs, I always use it in this situation. The reason is simple; if a directory is $BIGNUM large, and most of the files in it are measured in tens of kilobytes, your find command will more often than not send too many arguments xarg’s way. Your time is too precious a commodity to see whether or not this is one of the situations when the stars align and the mail quota is small enough that the directory doesn’t have too many files for xargs. Just use the for loop. If the server is reasonably fast, it will handle it gracefully.

Every once in a while you’ll run into an enlightened user who realizes, just as you’re about to go and mow through the .spam directory, that hey, there was an important email last week that somehow never got through. They’d like to be able to poke at the last week’s .spam emails. Which means you can’t just delete all the mails willy-nilly. This is why God invented the -mtime flag.

for file in $(find -type f -maxdepth 1 -mtime +7); do rm -fv $file; done

That -mtime +7 causes find to snag only the files that haven’t been modified in the last seven days.

I really can’t get over how useful a little command like find can be. I mean, I’ve tried to get over it. Brought it into therapy a couple of times. Still can’t shake how useful it is. I usually refer to this find tutorial when I trip over the syntax.

One final tip: before you start deleting data with reckless abandon, I highly recommend substituting “do echo $file;” for "do rm -fv $file;" in the above one-liners. It never hurts to make sure that you’re actually grabbing the files you think you are before you delete them.