← Back to Blog

Faster Terminal Searches with ripgrep, fzf, and bat: A Hands-On Review

You know the drill. A config value is hiding in a codebase of tens of thousands of lines. You reach for grep -r, stare at a wall of matching lines, then pipe it through find and sed to make sense of it. There is a faster way, and it is a stack of three open source tools that fit together: ripgrep for searching, fzf for interactive selection, and bat for readable output. All three are small, fast, and installed in seconds on Linux and macOS.

This is a hands-on review. Every command below I ran against a real codebase, so you can copy them and expect the same output shape.

Prerequisites

  • Linux or macOS with a package manager
  • A codebase or folder with a few thousand files to search against
  • grep and find installed (you already have them)

Install the three tools

Install each with your package manager.

# Debian/Ubuntu
sudo apt install ripgrep fzf bat

# macOS (Homebrew)
brew install ripgrep fzf bat

Debian names the bat binary batcat to avoid a clash with an older package. If the bat command is missing on your distro, use batcat or add an alias.

ripgrep: searching that keeps up

ripgrep is a grep replacement written in Rust. It respects .gitignore by default, so it skips node_modules, build output, and vendored code unless you tell it otherwise. That is the reason searches feel instant.

Search a folder, showing line numbers:

rg "TODO" src

Search only config file types:

rg --type json "name" .

List every file of a given type, the way find does but faster and honoring ignores:

rg --files -g '*.ts' src

Match files by filename glob:

rg "portfolio" -g '*.toml' .

Count matches per file, useful for spotting where a term clusters:

rg -c "astro" src

Answers two practical questions every day: where is this string, and what files match this pattern. The output is colorized by default and file names are written so that the next tool can swallow them.

fzf: turning matches into choices

fzf is a fuzzy finder. You type a few characters and every partial match ranks by relevance, with the best result highlighted. It is interactive, so it takes over the terminal while you filter.

Use it on its own to pick a file quickly:

fzf

The powerful part is composition. Feed fzf a stream of file names from ripgrep, pick one, and run a command on it:

vim "$(rg --files | fzf)"

That is one habit that replaces most of your tab-through-directories time. The pipeline is: list files fast, fuzzy-filter fast, act.

bat: output that reads itself

bat is cat with syntax highlighting, line numbers, and a git gutter. Point it at any file:

bat src/data/articles.ts

It also reads standard input, which is what makes it pair so well in a pipeline. Sequence the whole arm: search for a term, fuzzy-pick a file, then open that file pretty-printed at the matching line.

rg --line-number "TODO" "$(rg --files | fzf)" | bat

Verdict

Tool Does Best at Watch out for
ripgrep fast content + filename search searching gigabytes in milliseconds, respects .gitignore customize types via rg --add-type when your extension is unknown
fzf interactive fuzzy selection choosing from a long list fast, composing with any command interactive, so it needs a terminal
bat pretty printing files and stdin reading code with syntax highlighting and line numbers Debian may name it batcat

The three are strongest together. ripgrep does the heavy lifting, fzf lets you choose, bat makes the result readable. None of them replaces the others, and all three install in one line.

When to use these vs alternatives

  • grep / find: keep calling them when you need POSIX behavior on a machine where you cannot install anything. Once ripgrep and fzf are present, you will reach for them rarely.
  • ack / ag: ripgrep is generally faster and ships in more package managers; if you already know ack or ag you will learn ripgrep in minutes because the flags overlap.
  • IDE search (Ctrl+Shift+F): use the IDE intellisense when you need results tied to the project tree and integrated refactoring. Use the terminal stack when you want to search files outside the workspace or script the result.
  • Spotlight / app launchers: fuzzy pickers also exist as GUI tools (like Raycast, Alfred, or uLauncher). fzf does the same job inside the shell, which matters if you live in the terminal.
  • fd: a faster find that pairs with fzf and bat. If find is your bottleneck, add fd; ripgrep already covers most filename needs with --files.

Next steps

Wire fzf into your shell history and let it run a command on its own output.

# fuzzy-search your shell history
history | fzf

Read the man pages when a flag does not behave as expected: man rg, man fzf. Both document the type system and key bindings in depth. If you script a lot of searches, look at rg --files --json and fzf --preview, which lets you show file contents in a side pane while you filter.

Need Help Implementing This?

I help teams design and build scalable cloud infrastructure, DevOps pipelines, and production-grade systems.

Book a Free Consultation