Skip to content
0

NeoMutt Tutorial 13: Search and Filtering ​

Master NeoMutt's powerful search and filtering capabilities to quickly find and manage emails. Learn pattern modifiers, logical operators, and performance optimization techniques.

Overview ​

In this tutorial, you will:

  1. Understand the difference between search and limit
  2. Learn all pattern modifiers (~s, ~f, ~b, ~d, etc.)
  3. Combine patterns with logical operators
  4. Search by date ranges
  5. Optimize search performance with caching
  6. Create useful search macros

1. Search vs. Limit ​

NeoMutt provides two primary ways to find messages:

Purpose: Navigate to matching messages while keeping all messages visible.

KeyCommandAction
/searchJump to next matching message
\search-oppositeJump to previous matching message
nnext-matchFind next match of last pattern
Nprevious-matchFind previous match of last pattern

Use case: "Find the next email from John in my current view"

/ ~f john

Limit (l) ​

Purpose: Filter the view to show only matching messages.

KeyCommandAction
llimitShow only messages matching pattern
LlimitLimit (alternative binding)

Use case: "Show me only unread emails from this week"

l ~U ~d >1w

To remove a limit:

  • Press l and type ~A (matches all)
  • Press l and enter an empty pattern

When to Use Each ​

ScenarioUseExample
Quick navigationSearch (/)Find next attachment
Bulk operationsLimit (l)Delete all spam from a sender
Focused workLimit (l)Work only on unread messages
Context neededSearch (/)Find message while seeing surroundings

2. Pattern Modifiers ​

All search patterns use a tilde (~) prefix followed by a letter indicating what to search.

Header Patterns ​

PatternSearchesExample
~s "expr"Subject/~s "invoice"
~f "expr"From (sender)l~f "amazon"
~t "expr"To (recipient)/~t "support@"
~c "expr"Cc/Bccl~c "team"
~h "Header: value"Specific headerl~h 'X-Priority: 1'
~L "expr"Mailing list/~L "notifications"

Body Patterns ​

PatternSearchesExample
~b "expr"Message body/~b "meeting tomorrow"
~B "expr"Entire message (headers + body)l~B "project-alpha"

Performance Note: Body searches (~b, ~B) are slower than header searches. Enable caching (see section 5) for better performance.

Status Patterns ​

PatternDescriptionExample
~NNew messages (never viewed)l~N
~UUnread messagesl~U
~OOld messages (viewed but unread)l~O
~DDeleted messagesl~D
~FFlagged messages/~F
~TTagged messagesl~T
~rReplied messagesl~r
~QQueued/Postponed (drafts)l~Q
~aHas attachmentsl~a

Date Patterns ​

PatternDescriptionExample
~d [range]Messages in date rangel~d ">2d"
~R [range]Messages received in rangel~R "<1m"
~S [range]Messages sent in rangel~S ">1y"

See section 4 for detailed date range syntax.

Address Patterns ​

PatternDescriptionExample
~pMessages where you are in To/Ccl~p
~PMessages where you sent (From)l~P
~vMessages where you are in Tol~v
~VMessages where you are in Ccl~V

Size Patterns ​

PatternDescriptionExample
~z [range]Message size in bytesl~z ">1M"
~Z [range]Message size in kilobytesl~Z "<100"

3. Combining Patterns ​

Use logical operators to create complex search queries.

Logical Operators ​

OperatorMeaningExample
(space) or &ANDl~s report ~f boss
|OR/~s bug | ~s error
!NOTl~U !~f newsletter
()Groupingl (~f john | ~f jane) ~U

Operator Precedence ​

  1. ! (NOT) - highest precedence
  2. (space) or & (AND)
  3. \| (OR) - lowest precedence

Use parentheses to override default precedence:

muttrc
# Find unread emails from John OR Jane
l ~U (~f "John" | ~f "Jane")

# Find emails with attachments NOT from spam
l ~a !~f "spam@"

# Complex: Unread emails about "project" from team, excluding newsletters
l ~U & ~s "project" & (~f "team@" | ~c "team@") & !~L "newsletter"

Practical Examples ​

Find all unread work emails from this week:

l ~U ~d >1w ~f "@company.com"

Find emails with invoices that haven't been replied to:

l ~s "invoice" ~a !~r

Find flagged messages from a specific person:

/ ~F ~f "manager@"

Find all messages in a thread about a topic:

l ~s "budget meeting"

4. Date Range Syntax ​

The ~d pattern supports flexible date ranges.

Basic Format ​

~d [operator][number][unit]

Operators ​

OperatorMeaning
>After (newer than)
<Before (older than)
(none)On (exact date)

Units ​

UnitMeaning
dDays
wWeeks
mMonths
yYears

Examples ​

PatternDescription
~d >2dNewer than 2 days ago
~d <1wOlder than 1 week ago
~d >1mNewer than 1 month ago
~d <1yOlder than 1 year ago
~d 15/01/2025On January 15, 2025
~d 01/01/2025-31/01/2025Between Jan 1 and Jan 31, 2025
~d >01/01/2025After January 1, 2025
~d <01/01/2025Before January 1, 2025

Date Format Variations ​

NeoMutt accepts multiple date formats:

~d DD/MM/YYYY        # 15/01/2025
~d MM/DD/YYYY        # 01/15/2025 (US format)
~d YYYY-MM-DD        # 2025-01-15 (ISO format)

Practical Date Searches ​

Today's emails:

l ~d >0d

This week:

l ~d >7d

Last month:

l ~d >1m <2m

Older than 6 months (for archiving):

l ~d <6m

Year-to-date:

l ~d >01/01/2025

5. Performance Optimization ​

Body searches can be slow, especially over IMAP. Caching dramatically improves performance.

Enable Message Caching ​

Add to ~/.config/neomutt/options:

muttrc
# Cache headers for faster searching
set header_cache = "~/.cache/neomutt/headers"

# Cache message bodies for faster body searches
set message_cachedir = "~/.cache/neomutt/bodies"

Create Cache Directories ​

bash
mkdir -p ~/.cache/neomutt/{headers,bodies}
chmod 700 ~/.cache/neomutt

How Caching Works ​

  1. First search: NeoMutt downloads and caches message bodies (slow)
  2. Subsequent searches: NeoMutt searches the local cache (fast)

Cache Maintenance ​

Clear cache if needed:

bash
rm -rf ~/.cache/neomutt/headers/*
rm -rf ~/.cache/neomutt/bodies/*

Cache size management: NeoMutt automatically manages cache size, but you can manually prune old caches periodically.

Search Performance Tips ​

  1. Use specific patterns: ~s "invoice" is faster than ~B "invoice"
  2. Limit scope first: Use l~f sender then search within results
  3. Cache enabled: Always enable caching for IMAP accounts
  4. Avoid ~B when possible: Search specific fields instead

6. Quote Handling in Patterns ​

Understanding when to use quotes in search patterns.

No Quotes Needed ​

When your search term has no spaces:

muttrc
/~s invoice          # Single word
l~f ^user@           # Regex without spaces
l~U&~a               # Combined status patterns

For literal phrases with spaces:

muttrc
l~b 'quarterly report'           # Exact phrase
/~f 'John Smith <john@example>'  # Full name + email

Double Quotes ​

When you need variable expansion:

muttrc
l~s "Invoice from $USER"         # $USER is expanded

Best Practice: Use single quotes by default. Use double quotes only when you need variable or command substitution.

7. Regular Expressions ​

All search patterns support POSIX Extended Regular Expressions (ERE).

Common Regex Patterns ​

PatternMeaningExample
^Start of line/~s "^Re:" (subjects starting with "Re:")
$End of line/~s "report$" (subjects ending with "report")
.Any character/~b "v1.0" (matches v1.0, v120, etc.)
\.Literal period/~b "v1\.0" (matches only v1.0)
*Zero or more/~f "support.*"
+One or more/~s "error+"
?Zero or one/~s "colou?r" (matches color or colour)
[]Character class/~f "[ae]@company"
()Grouping/~s "(bug | error)"

Regex Examples ​

Subjects starting with "Fwd:":

/~s "^Fwd:"

Emails containing version numbers:

/~b "v[0-9]+\.[0-9]+\.[0-9]+"

From specific domain or subdomain:

l~f "@(.+\.)?company\.com$"

8. Useful Search Macros ​

Add these to ~/.config/neomutt/mappings:

muttrc
# =============================================================================
# Search Macros
# =============================================================================

# Quick limit: Unread only
macro index lu "<limit>~U\n" "Limit to unread"

# Quick limit: This week
macro index lw "<limit>~d >7d\n" "Limit to this week"

# Quick limit: This month
macro index lm "<limit>~d >1m\n" "Limit to this month"

# Quick limit: With attachments
macro index la "<limit>~a\n" "Limit to messages with attachments"

# Quick limit: From specific sender (prompts for input)
macro index lf "<limit>~f " "Limit by sender"

# Quick limit: By subject (prompts for input)
macro index ls "<limit>~s " "Limit by subject"

# Show all messages (remove any limit)
macro index lA "<limit>~A\n" "Show all messages"

# Find next unread from current sender
macro index nu "<limit>~U ~f " "Next unread from sender"

# Search body for term (with caching)
macro index sb "<search>~b " "Search body"

# Find all drafts (postponed messages)
macro index qd "<limit>~Q\n" "Show drafts"

# Find flagged messages
macro index qf "<limit>~F\n" "Show flagged"

# Find messages where I'm in To field
macro index qp "<limit>~v\n" "Messages addressed to me"

# Complex: Unread, to me, this week
macro index complex "<limit>~U & ~v & ~d >7d\n" "Unread to me this week"

9. Practical Workflows ​

Inbox Triage ​

1. l~U                    # Limit to unread
2. Process each message:
   - r to reply
   - d to delete
   - s to save/archive
3. l~A                    # Remove limit
4. $                      # Sync

Finding Old Conversations ​

1. l~d <6m                # Older than 6 months
2. /~s "project name"     # Search within old messages
3. <Enter> to read

Bulk Delete Spam ​

1. l~f "spam-sender@"     # Limit to spam sender
2. *                      # Tag all matching
3. d                      # Delete tagged
4. l~A                    # Remove limit
5. $                      # Sync

Archive Old Messages ​

1. l~d <1y                # Messages older than 1 year
2. *                      # Tag all
3. s +Archive<Enter>      # Save to Archive folder
4. l~A                    # Remove limit
5. $                      # Sync deletions

Find Unanswered Emails ​

1. l~U !~r                # Unread and not replied
2. ~v                     # Also where I'm in To field
3. Process as needed

10. Troubleshooting ​

Search Returns No Results ​

Possible causes:

  • Pattern syntax error
  • Wrong field (searching subject when term is in body)
  • Messages don't match criteria

Solutions:

  • Try ~B for whole-message search
  • Check for typos in search term
  • Use broader pattern first, then narrow down

Body Search is Very Slow ​

Cause: Searching uncached message bodies over IMAP

Solution:

muttrc
set message_cachedir = "~/.cache/neomutt/bodies"

Pattern with Spaces Not Working ​

Cause: Spaces interpreted as AND operator

Solution: Use quotes

# Wrong:
l~b quarterly report

# Correct:
l~b 'quarterly report'

Case Sensitivity Issues ​

NeoMutt searches are generally case-insensitive by default. For case-sensitive searches, use explicit regex:

# Case-sensitive subject search
/~s "^IMPORTANT:"

11. What's Next? ​

You've now mastered searching and filtering in NeoMutt. In the next tutorial, we'll cover:

  • Viewing attachments (HTML, PDF, images)
  • mailcap configuration for MIME types
  • Adding attachments efficiently with fzf
  • Multi-file attachment workflows

Continue to Tutorial 14: Attachments.


Series Navigation: Overview → 11: Basic IMAP → 12: Keymaps → 13: Search → 14: Attachments → 15: Local Mirror

最近更新