Virtual Folders in mutt

by Kyle Rankin

Related link:

My email is generally well-organized. I have a lot of different folders and procmail rules that automatically move email to the various categories of email I've set up. Sometimes, though, I can't exactly remember which category a message is in. While mutt, my preferred email client, is great at searching for a term within a folder, it isn't as easy to search all of your email folders at once. I found a few possible solutions to this problem, and ended up rolling my own solution.

I was first inspired by this post that described using mairix to create a virtual folder in mutt. Mairix indexes all of your email folders, and allows you to search through this index with basic keyword searches. It then outputs the results into a maildir (or mbox if you want) so you can treat it like a virtual folder.

I set up mairix for a bit and tried it out, however I realized that most of my searches aren't simple "what emails contain these single words in them" much of the time. Some times I want to search for two words next to each other, but that's something mairix doesn't seem to be able to do. Sometimes I even want to use regular expressions in my searches, which mairix doesn't support.

My solution is a script called "maildirsearch" and looks like this:


FOLDERS=`awk '{print $2}' $HOME/.mutt/mailboxes | sed 's/^"\=\(.*\)\"$/\1 /' \
| xargs echo`


for i in $FOLDERS
for j in `egrep -lR "$@" $MAILDIRS/$i`
ln -s $j $VFOLDERPATH/.;

I store my mail in a series of maildirs on my laptop in ~/mail/. The FOLDERS environment variable is populated with a one-liner that turns my .mutt/mailboxes file from this:

. . .
mailboxes "=oreilly"
mailboxes "=blog"
mailboxes "=nblug"
mailboxes "=google_alerts"
mailboxes "=debian"
mailboxes "=sent-mail"

into a list of folders separated by spaces. Then I egrep through each folder for my search term, finally symlinking any results into my virtual folder that I called "search" and put with the rest of my maildirs.

I realized that when I ran this search in mutt, what would be nice is for mutt to automatically change to this new folder while it was being populated with email. So I created a wrapper script that runs this script in the background, and then runs an extra instance of mutt inside itself, open to my virtual folder. It's a bit of a hack, but I can't seem to find a way yet to send commands to a running mutt process from outside mutt. I called this script "muttsearch":


$HOME/bin/maildirsearch "$@" &
sleep 1;
mutt -f "=$VFOLDER";

Basically, since it runs mutt -f "=search", I can watch my search results as they appear, so I can go ahead and read through them without having to wait for the search to finish. Plus I can use all of the standard mutt filtering techniques at that point to refine the search. All that was left is to add a macro to my mutt config:

# search macro
macro index \eM "$HOME/bin/muttsearch "
macro browser \eM "$HOME/bin/muttsearch "

Now I can just type Esc-M from within mutt and type in my search term. I think for the future I'm going to extend this idea to provide other types of virtual folders from within mutt, possibly to create a folder of flagged messages on the fly.

How do you manage virtual folders in mutt? In your preferred email client?


2005-02-03 14:36:34
A small change to avoid double-linking
I noticed when I ran the script that it tried to link the messages to themselves in $VFOLDER and gave me the following error message:

ln: Maildir/.Search/cur/1107194183.21186_45.panix3:2,S: File exists

so in maildirsearch I changed

for i in $FOLDERS


for i in ${FOLDERS/$VFOLDER/}

and it seems to work. Note that this is a bash solution. I don't know if it will work in other shells.

I also put an -f flag on rm so it won't send me an error message when $VFOLDER is empty.

2005-02-09 14:43:25
A small change to avoid double-linking
Um, great script, by the way. It's small and elegant.

I've also been trying out nmzmail, another possible mutt-search solution.

And sorry about the ugly spacing in my previous post.