fmd — Find Markdown files by metadata
The command-line companion for your knowledge base.
fmd finds Markdown files by tags, frontmatter, and custom metadata. Pipe the results to xargs to move notes by tags, to grep to search content, or to any Unix tool to build custom workflows. If you organize notes with metadata, fmd gives you the power to act on it.
Features
- 🗂 Metadata-aware — Understands YAML frontmatter and inline
#tags - 🔍 Flexible filtering — By tag, title, filename, date, or any custom field
- 🧩 Unix-friendly — Compose with
xargs,grep,fzf - 🎯 Zero-setup — No database, no indexing required
- ⚡ Fast — Smart filtering, reads metadata only, parallel processing
Quick Start
Installation
# From crates.io (recommended)
# From source
Basic Usage
# List all Markdown files
# Find by tag
# Find by title (YAML frontmatter or # heading)
# Find by author
# Find by filename
# Find by custom field
# Find by date range
# Combine filters (AND logic across types)
# → (tag=work) AND (title=meeting) AND (author=John)
# Search entire file content (not just first 10 lines)
Metadata Format Support
fmd understands two metadata formats:
1. YAML Frontmatter
title: My Note
tags: [python, rust, cli]
author: John Doe
date: 2025-01-15
status: draft
Multi-line format:
title: Setup Guide
tags:
- - -
2. Inline Format
tags: #python #rust #cli
author: John Doe
date: 2025-01-15
Note: By default, fmd scans the first 10 lines for inline metadata. Use --full-text to search the entire file.
Usage Examples
Search by Tags
# Single tag
# Multiple tags (OR logic)
# Full-text tag search (searches #tag in entire file)
Search by Title
# Find notes with "meeting" in title
# Regex patterns supported
Search by Filename
# Case-sensitive by default
# Case-insensitive
Search by Author
# Single author
# Multiple authors (OR logic)
# Case-insensitive matching
# Partial matching
Search by Custom Fields
# By status
# By date (partial match)
Search by Date Range
Date filtering checks the date, created, updated, and modified fields. A file matches if any of these dates satisfies the filter.
# Files from 2025 onwards
# Files before a specific date
# Date range (Q1 2025)
# Recent notes (last month)
# Combine with other filters
Supported date fields (checked in order):
date:— Primary date fieldcreated:— Creation dateupdated:— Last update datemodified:— Last modification date
Date format: YYYY-MM-DD (ISO 8601)
Combining Filters
Filters of the same type use OR logic, while different types use AND logic:
Same Type → OR
Different Types → AND
Complex Example
# (tag=work OR tag=personal) AND title=meeting AND author=John
Full-Text Search
By default, fmd scans only the first 10 lines for inline tags (controlled by --head). Use --full-text to search the entire file:
| Mode | YAML tags: |
Inline tags: |
Content #tag |
|---|---|---|---|
| Default | ✓ | ✓ (first 10 lines) | ✗ |
--full-text |
✓ | ✓ (entire file) | ✓ |
Command-Line Options
| Option | Description |
|---|---|
-t, --tag TAG |
Filter by tag (case-insensitive) |
-T, --title PAT |
Filter by title (case-insensitive, regex) |
-a, --author PAT |
Filter by author (case-insensitive) |
-n, --name PAT |
Filter by filename (regex) |
-f, --field F:P |
Filter by frontmatter field (format: field:pattern) |
--date-after DATE |
Filter files with dates on or after DATE (format: YYYY-MM-DD) |
--date-before DATE |
Filter files with dates on or before DATE (format: YYYY-MM-DD) |
--glob GLOB |
File pattern to match (default: **/*.md) |
-d, --depth N |
Limit search depth (1=current dir only) |
--head N |
Lines to scan for metadata (default: 10) |
--full-text |
Search entire file content |
-i, --ignore-case |
Case-insensitive matching for --name filter |
-0 |
NUL-delimited output (safe for filenames with spaces) |
-v, --verbose |
Show verbose output including warnings and errors |
-h, --help |
Show help message |
Usage with Unix Tools
fmd is designed to work seamlessly with standard Unix tools. Here are practical examples:
Search and Edit
# Search file contents
|
# Edit all draft files
|
# Interactive selection with fzf
| |
File Management
# Move files (safe with spaces using -0)
|
# Move files from current directory only
|
# Backup recent files (last 3 months)
|
# Archive old notes (before 2024)
|
# Create tar archive
|
Analysis and Reporting
# Count files by tag
|
# List file details (safe with spaces)
|
# Find Q1 2025 work notes
# Find beginner tutorials
# Recent meeting notes
Building from Source
Requirements: Rust 1.91+ (install from rustup.rs)
# Clone and install
# Or just build without installing
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT License © 2025 Enjan Chou
Find Markdown files by what matters: metadata.