Terminal showing a list of file paths filtered by an interactive search

fzf is an MIT-licensed command-line fuzzy finder that turns any list of text into a menu that filters as you type. With more than 82,000 stars on GitHub it is one of the most widely used terminal utilities, and its most immediate payoff requires learning almost nothing: three keyboard shortcuts for searching history, inserting file paths and changing directory.

fzf key points in 30 seconds

  • fzf reads a list on standard input and prints the chosen line on standard output.
  • Ctrl+R searches shell history, Ctrl+T inserts paths and Alt+C changes directory.
  • Its search syntax adds exact, prefix, suffix, negation and OR matching without regex.
  • It installs with brew, apt, dnf, pacman, winget or the project’s own installer.
  • It is free software under the MIT license, written in Go.

The problem it solves is an everyday one. A command you typed weeks ago is still in your history, but finding it means chaining history | grep with ever narrower filters. The same happens when you look for a file and only remember part of its name. Either way you have a list and a rough idea of what you want, and fzf lets you type into that list and watch it shrink in real time.

It already appears in our roundup of 12 modern tools for the Linux terminal, but it deserves its own guide because its value grows the more you combine it with other commands.

How it works and how to search

fzf is a Unix filter: it takes lines on standard input, shows a search box and writes the selected line to standard output. It does not care whether those lines are files, git branches, processes or containers, which is why it fits with almost any command. The basic shape is command_that_prints_a_list | fzf.

Fuzzy matching means the characters you type must appear in order, but not next to each other. In a list containing src/handlers/user.go, src/models/user.go and test/user_test.go, typing shu leaves only the first path, because it is the only one with an s, then an h, then a u. The --filter mode lets you test this without the interface:

printf "src/handlers/user.gonsrc/models/user.gontest/user_test.gon" | fzf --filter="shu"Code language: JavaScript (javascript)

When fuzzy search returns too much, fzf offers operators that need no regular expressions. Terms are space-separated and combine:

  • sbtrkt: fuzzy match.
  • 'word: exact match; 'word', exact match at word boundaries.
  • ^prefix: starts with.
  • suffix$: ends with.
  • !word: does not contain; also !^prefix and !suffix$.
  • a | b: either.

For example, .go !test returns Go files whose names do not contain test.

Installation and the three essential shortcuts

fzf is in almost every distribution’s repositories (apt, dnf, pacman, apk), in Homebrew on macOS and in Chocolatey, Scoop, Winget or MSYS2 on Windows. Some distribution packages can lag well behind the latest release, and several features changed between versions. For the newest version, the project publishes binaries on GitHub and an installer:

git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/installCode language: JavaScript (javascript)

The most important step is enabling shell integration. On recent versions one line in your config file is enough:

# ~/.bashrc
eval "$(fzf --bash)"

# ~/.zshrc
source <(fzf --zsh)

# ~/.config/fish/config.fish
fzf --fish | sourceCode language: PHP (php)

That brings three shortcuts. Ctrl+R replaces reverse history search with a filterable list: type ffmpeg scale and every matching command appears. Ctrl+T inserts the path of a chosen file or directory at the cursor, handy in the middle of a command such as vim. Alt+C changes into a chosen subdirectory using the same search.

Shell integration also adds fuzzy completion with ** followed by Tab: vim **<Tab> for files, kill -9 **<Tab> for processes or ssh **<Tab> for hosts. Fish uses Shift+Tab instead.

Previews and useful combinations

The --preview option runs a command on the highlighted line and shows the output alongside, with {} standing for the current item. With bat you get syntax highlighting, and fzf also supports image previews on terminals that speak the Kitty, iTerm2 or Sixel protocols.

fzf --preview 'bat --color=always {}'Code language: JavaScript (javascript)

Every other use follows the same pattern: produce a list, pipe it to fzf and act on the choice. A few examples:

# Check out a git branch
git branch | fzf | xargs git checkout

# Kill a process
ps aux | fzf | awk '{print $2}' | xargs kill

# Shell into a Docker container
docker ps --format '{{.Names}}' | fzf | xargs -I {} docker exec -it {} sh

# Search environment variables
env | fzfCode language: PHP (php)

Be careful with these one-liners on production servers: a kill or checkout on the wrong line cannot be undone. The -m option lets you select several lines with Tab, so it pays to check the selection before pressing Enter.

Defaults are set through environment variables. FZF_DEFAULT_OPTS controls the look, for example --height 40% --layout reverse --border for a compact window below the prompt, and FZF_DEFAULT_COMMAND chooses what generates the file list. Using fd --type f --hidden --exclude .git makes it faster and respects .gitignore. Each shortcut also has its own variables, such as FZF_CTRL_T_OPTS, FZF_CTRL_R_OPTS or FZF_ALT_C_COMMAND.

fzf does not replace grep or rg in unattended scripts or for well-defined exact searches: it is an interactive tool for when you know roughly what you want. Vim users also get the fzf.vim plugin, and on tmux 3.3 or later the --popup option opens fzf in a floating window. For more terminal tooling, see our list of eight CLI tools that still matter in the age of AI agents.

Frequently asked questions

What is fzf?

A command-line fuzzy finder that interactively filters any list of text and returns the chosen line.

How do I enable Ctrl+R and Ctrl+T with fzf?

Add eval "$(fzf --bash)" to ~/.bashrc, source <(fzf --zsh) to ~/.zshrc, or fzf --fish | source in fish.

Why doesn’t fzf –bash work on my distribution?

Most likely the distribution package is old. Those options need recent versions; the project’s installer or binaries give you the latest.

What license does fzf use?

The MIT license.

Sources:

Scroll to Top