Skip to main content

Fuzzy and Exact Search Syntax

fzf supports multiple matching modes within a single query. You can mix fuzzy terms, exact strings, anchors, and negations in one search expression.

Core Idea

fzf queries are space-separated tokens. Each token is matched independently, and all tokens must match for a result to appear (AND logic). Use | for OR between tokens.

Token Types

TokenSyntaxMatches
FuzzywordFuzzy match — chars in order, not necessarily adjacent
Exact'wordExact substring match (apostrophe prefix)
Prefix exact^wordLine must start with word
Suffix exactword$Line must end with word
Exact full-line^word$Line equals word exactly
Negation fuzzy!wordMust NOT fuzzy-match word
Negation exact!'wordMust NOT contain word
OR operator`tok1tok2`

Fuzzy Matching

# Query: "nvconf"
# Matches: ~/.config/nvim/lua/config/options.lua ← all chars present in order
# Matches: /etc/nginx/nginx.conf ← n, v, c, o, n, f all present
# Scores higher when chars are consecutive and near start of words

ls ~/.config | fzf
# Type: nvim → matches "nvim" directory
# Type: nvco → matches "nvim/lua/config/options.lua"

Exact Match (')

Prefix your term with ' (single apostrophe) for an exact substring match:

# Only lines that literally contain "nginx.conf"
ls /etc -R | fzf --query "'nginx.conf"

# Exact "error" (case insensitive by default)
cat /var/log/syslog | fzf --query "'error"

Anchored Matching

# Lines starting with "server"
cat /etc/nginx/nginx.conf | fzf --query "^server"

# Lines ending with ".conf"
ls /etc | fzf --query ".conf$"

# Lines that are exactly "nginx"
ls /etc | fzf --query "^nginx$"

# Prefix fuzzy: line starts with n, v, i, m in order
ls | fzf --query "^nvim"

Negation

Prefix with ! to exclude matches:

# Show everything EXCEPT files containing "backup"
ls | fzf --query "!backup"

# Exact negation: exclude lines containing ".log"
ls | fzf --query "!'\.log"

# Exclude lines starting with "."
ls -a | fzf --query "!^."

AND Logic (Multiple Tokens)

Tokens separated by spaces are ALL required to match (AND):

# Must match "nginx" AND ".conf"
ls /etc -R | fzf --query "nginx .conf"

# Must match both "error" AND "2024"
cat /var/log/syslog | fzf --query "error 2024"

# Must match "server" AND NOT "upstream"
cat nginx.conf | fzf --query "server !upstream"

OR Logic (|)

Use | (pipe, with spaces) for OR between terms:

# Lines matching "python" OR "ruby"
ls /usr/bin | fzf --query "python | ruby"

# Exact "nginx.conf" OR exact "apache.conf"
ls /etc -R | fzf --query "'nginx.conf | 'apache.conf"

Case Sensitivity

By default, fzf is case-insensitive. Behavior changes when the query contains uppercase:

# Case insensitive (no uppercase in query)
ls | fzf --query "nginx" # matches Nginx, NGINX, nginx

# Case sensitive (uppercase present)
ls | fzf --query "Nginx" # matches only Nginx (not nginx)

Force case behavior with flags:

fzf -i          # always case-insensitive
fzf +i # always case-sensitive
fzf --smart-case # default: smart (mixed case = case-sensitive)

Regex Matching (--algo)

fzf's default algorithmis fuzzy (v2). For exact regex on the query:

# Regex mode via filter flag
ls | fzf --filter "^[0-9]" # non-interactive: lines starting with digit

# Note: fzf doesn't support full regex interactively by default
# Use rg or awk to pre-filter, then pipe to fzf
ls /var/log | grep -E "\.log$" | fzf

Practical Search Examples

# Find all Python files except test files
find . -name "*.py" | fzf --query "!test"

# Find nginx configs but not backups
ls /etc/nginx -R | fzf --query "^sites .conf$ !backup"

# Find error log lines from today
cat /var/log/syslog | fzf --query "'$(date +%b\ %d) error"

# Find docker images with "python" or "node" tags
docker images | fzf --query "python | node !none"

What's Next