Search Operators and Scoring
Understanding how fzf scores matches helps you write better queries and design more effective fzf-based tools.
The Scoring Algorithm
fzf uses the fzf (v2) scoring algorithm. It assigns scores based on:
Higher score = better match
| Factor | Effect on score |
|---|---|
| Consecutive matched chars | +++ Higher score |
Match at word boundary (-, /, ., _, space) | ++ Higher score |
| Match at start of string | ++ Higher score |
| Match at start of basename | ++ Higher score |
| Far apart matched chars | - Lower score |
| Matched chars only in middle | - Lower score |
Example Scoring
Query: "mvc"
Candidate: mvc-framework ← score: 90 (all chars at start, consecutive)
Candidate: my-view-controller ← score: 75 (word boundaries but not consecutive)
Candidate: some-movie-creator ← score: 40 (chars spread out)
Controlling Sort
# Default: sorted by match score (best first)
ls | fzf
# Disable sort: maintain input order
ls | fzf --no-sort
# Toggle sort interactively
ls | fzf --bind "ctrl-s:toggle-sort"
The --tiebreak Flag
When multiple items have equal scores, --tiebreak determines which comes first:
fzf --tiebreak=length # shorter strings first
fzf --tiebreak=begin # earlier match position first
fzf --tiebreak=end # later match position first
fzf --tiebreak=index # original input order
fzf --tiebreak=chunk # chunk-based (default for large items)
# Combine multiple tiebreakers
fzf --tiebreak=length,begin,index
The --algo Flag
fzf --algo=v1 # simpler algorithm (faster, less accurate)
fzf --algo=v2 # default: full fuzzy algorithm (best accuracy)
Use v1 only for extremely large lists (millions of items) where speed matters more than precision.
Tabular Data — --nth and --delimiter
When input is tabular (CSV, TSV, space-separated), restrict scoring to specific columns:
# Score only against column 2 of space-separated ps output
ps aux | fzf --nth=2
# Score against columns 1 and 3 of colon-separated /etc/passwd
cat /etc/passwd | fzf --delimiter=: --nth=1,3
# Score against everything after the first tab
cat data.tsv | fzf --delimiter=$'\t' --nth=2..
# Score only basename of path (ignore directory part)
find . -name "*.conf" | fzf --nth=-1 --delimiter=/
# -1 means last field (basename)
--scheme — Optimized Match Scoring per Use Case
fzf --scheme=default # balanced: file/non-file mix
fzf --scheme=path # optimized for file paths
fzf --scheme=history # optimized for shell history (recent = higher)
fzf --scheme=history --tiebreak=index # shell history: recent items first
Complete Token Reference
TERM Fuzzy match
'TERM Exact match
^TERM Starts with (prefix exact)
TERM$ Ends with (suffix exact)
^TERM$ Full line equals TERM exactly
!TERM NOT fuzzy match
!'TERM NOT exact match
!^TERM Does NOT start with
!TERM$ Does NOT end with
Multiple space-separated terms = AND
TERM1 | TERM2 = OR (must use spaces around |)
Realistic Multi-Token Queries
# nginx error logs from this year, excluding health checks
cat /var/log/nginx/access.log | fzf --query "'2024 '500 | '502 | '503 !'health"
# Find Python files, not in venv, not __pycache__
find . | fzf --query ".py$ !venv !__pycache__ !.pyc$"
# Docker: running containers with web in name, not paused
docker ps -a | fzf --query "web !Exited !Paused"
# Kubernetes pods in production, not running (find errors)
kubectl get pods -A | fzf --query "production !Running !Completed"