
The Fuzzy Limitation
FZF is famous for its fuzzy matching. You type fbr and it finds foo/bar/readme.md. For many users, this “vibe-based” search is enough. But for power users managing repositories with 100,000 files, fuzzy matching can be a hindrance. Sometimes you don’t want “close matches”—you want exactly what you typed.
To master FZF, you have to move beyond the fuzzy and embrace the Extended Search Mode.
1. The Ninja Prefixes (Precision Syntax)
By default, FZF is in “Extended Search Mode,” which means you can use specialized characters to bypass the fuzzy engine.
| Prefix | Name | Example | Result |
|---|---|---|---|
' |
Exact-match | 'wild |
Matches “wild” but NOT “w i l d”. |
^ |
Prefix-anchor | ^src |
Matches lines that start with “src”. |
$ |
Suffix-anchor | .js$ |
Matches lines that end with “.js”. |
! |
Inverse-match | !test |
Excludes any lines containing “test”. |
| ` | ` | OR-match | `py |
The “Pro Query”
You can combine these with spaces.
^src 'utils .ts$ !spec
Translation: Find all files that start with src, contain the exact word utils, end with .ts, and do NOT have spec in the name.
2. Case Sensitivity: The Smart Way
FZF uses Smart Case by default.
- If your query is all lowercase, it is case-insensitive.
- If you type even one capital letter, it becomes case-sensitive.
If you hate this behavior, you can force your preference in your .zshrc:
export FZF_DEFAULT_OPTS="--case-insensitive" # Always ignore case
# OR
export FZF_DEFAULT_OPTS="--exact" # Disable fuzzy by default3. Live-Reloading with Ripgrep (Global Regex)
This is the “Black Belt” of FZF. Instead of having FZF filter a static list, you can bind FZF’s input to a live Ripgrep process. This allows you to use full PCRE2 Regular Expressions (Perl Compatible) to search through millions of lines of code in real-time.
The Live-Grep Script:
Add this function to your shell:
frg() {
fzf --ansi --disabled --query "$1" \
--bind "change:reload:rg --column --line-number --no-heading --color=always --smart-case {q} || true" \
--preview 'bat --style=numbers --color=always --highlight-line {2} {1}'
}Why This is Better:
- Search Everywhere: You aren’t limited to filenames; you are searching inside the content.
- Dynamic Filtering: As you type, Ripgrep restarts the search.
- Powerful Syntax: You can use advanced regex like
\b[A-Z][a-z]+\band see the results instantly.
4. Multi-Select and Post-Processing
Did you know you can select multiple items in FZF?
Run FZF with the -m flag. Use Tab to select items and Enter to output all of them.
Usecase: Bulk Deleting Branches
git branch | fzf -m | xargs git branch -DBe careful with this one!
Conclusion
FZF is often marketed as a “simple” tool, but its depth is staggering. By moving from “fuzzy vibes” to “regex precision,” you turn your terminal from a basic text interface into a surgical data-mining engine. Stop scrolling through ls output and start querying your filesystem like a database.
References & Further Reading
- Junegunn Choi: FZF Official Search Syntax Guide
- Grep.app: How to search 500k repos at once
- The BurnSushi Blog: Ripgrep Regex Internals
- Effective Shell: Navigating with FZF