fzf Fuzzy Finder

fzf cheatsheet — fuzzy find files, commands, git branches. Ctrl+R history search, Ctrl+T file search, fzf --preview, fzf with ripgrep. Full interactive filter reference.

7 min read

What it is

fzf is an interactive command-line fuzzy finder that allows you to quickly search and select from lists of files, directories, command history, and more. You reach for it when you need to find something in a potentially long list without typing the exact name.

Installation

Linux

# Using apt (Debian/Ubuntu)
sudo apt update && sudo apt install fzf

# Using dnf (Fedora)
sudo dnf install fzf

# Using pacman (Arch Linux)
sudo pacman -S fzf

# Using git (if not in package manager or for latest version)
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/install

macOS

# Using Homebrew
brew install fzf

# To install useful key bindings and fuzzy auto-completion:
$(brew --prefix)/opt/fzf/install

Windows

fzf is not officially supported on Windows, but you can install it via package managers like Chocolatey or Scoop, or by building from source.

# Using Chocolatey
choco install fzf

# Using Scoop
scoop install fzf

Core Concepts

  • Fuzzy Matching: fzf doesn’t require exact string matches. You can type parts of a name, and it will find relevant items. The matching is "fuzzy," meaning it accounts for skipped characters and order.
  • Interactive Interface: fzf presents an interactive terminal interface where you type your query, and the results update in real-time.
  • Input Source: fzf reads from standard input (stdin) to generate its list. This makes it incredibly versatile as you can pipe the output of almost any command into fzf.
  • Output: By default, fzf prints the selected item(s) to standard output (stdout).

Commands / Usage

Basic Usage

  • Find files in the current directory and subdirectories:

    fzf
    

    This command, when run without input, uses find . by default to list files.

  • Find files from a specific directory:

    find /path/to/directory | fzf
    

    Lists files within /path/to/directory and its subdirectories.

  • Select a command from history:

    history | fzf
    

    Searches your shell history and prints the selected command.

  • Select a Git branch:

    git branch | fzf
    

    Lists local Git branches and prints the selected one.

Key Flags and Options

Input and Output Control

  • --height LINES: Set the height of the finder window.

    ls | fzf --height 40%
    

    Displays the file list in a finder window that takes up 40% of the terminal height.

  • --layout=reverse: Display the finder window at the bottom of the terminal.

    ls | fzf --layout=reverse
    

    Puts the fzf interface at the bottom of the screen.

  • --multi: Enable multi-selection (using Tab and Shift+Tab).

    ls | fzf --multi
    

    Allows you to select multiple files by pressing Tab. The output will be space-separated.

  • --print0: Print selected items delimited by a null character. Useful for filenames with spaces.

    ls | fzf --multi --print0 | xargs -0 rm
    

    Safely deletes multiple selected files, even those with spaces in their names.

  • --preview COMMAND: Show a preview of the currently highlighted item.

    find . -type f | fzf --preview 'bat --color=always {}'
    

    Shows the content of the highlighted file using bat (a cat clone with syntax highlighting). {} is a placeholder for the current item.

  • --preview-window POSITION: Control the position of the preview window.

    find . -type f | fzf --preview 'cat {}' --preview-window right:60%
    

    Opens the preview window on the right, taking up 60% of the terminal width. Other positions: up, down, left.

Matching and Filtering

  • --exact: Require an exact match.

    find . -type f | fzf --exact
    

    Only shows files whose names exactly match your input.

  • --case-sensitive: Enable case-sensitive matching.

    find . -type f | fzf --case-sensitive
    

    file.txt will not match FILE.TXT unless you type FILE.TXT.

  • --word: Trigger fuzzy matching only for the current word.

    find . -type f | fzf --word
    

    Useful when you have multiple words in your query.

  • --bind KEY:ACTION: Bind keys to specific actions.

    fzf --bind 'ctrl-o:execute(code {})'
    

    Pressing Ctrl+O when an item is highlighted will open it in VS Code.

  • --bind KEY:+ACTION: Bind keys to multiple actions.

    fzf --bind 'enter:execute-silent(echo {} >> selected_files.txt)'
    

    Pressing Enter appends the selected item to selected_files.txt without closing fzf.

Actions

  • execute:COMMAND: Execute a command with the selected item as an argument.

    find . -type f | fzf --bind 'enter:execute(vim {})'
    

    Opens the selected file in Vim.

  • execute-silent:COMMAND: Execute a command silently (without closing fzf).

    find . -type f | fzf --bind 'ctrl-y:execute-silent(echo {} | pbcopy)'
    

    Copies the selected filename to the clipboard using pbcopy (macOS). Use xclip -selection clipboard on Linux.

  • accept: The default action when you press Enter (prints the selection to stdout).

  • abort: Exit fzf without printing a selection.

  • toggle-preview: Show/hide the preview window.

Environment Variables

  • FZF_DEFAULT_COMMAND: The default command to execute when fzf is run without input.

    # Set in your .bashrc or .zshrc
    export FZF_DEFAULT_COMMAND='find . -type f'
    

    This makes fzf default to finding files.

  • FZF_DEFAULT_OPTS: Default options for fzf.

    # Set in your .bashrc or .zshrc
    export FZF_DEFAULT_OPTS='--layout=reverse --height=50% --preview="bat --color=always {}"'
    

    Applies these options every time fzf is run.

Common Patterns

  • Open any file with your default editor (e.g., Vim):

    vim $(fzf)
    

    This is a very common and powerful pattern. fzf lists files, you select one, and vim opens it.

  • Change directory interactively:

    cd $(find . -type d | fzf)
    

    Finds directories, lets you select one, and then changes to that directory.

  • Edit shell configuration files:

    vim ~/.config/nvim/init.vim # Or ~/.bashrc, ~/.zshrc, etc.
    

    A common use case is to have a shortcut like vconfig that runs:

    vim $(find ~/.config ~/.* -type f | fzf --preview 'cat {}' --height 80%)
    
  • Select and git checkout a branch:

    git checkout $(git branch | fzf | tr -d ' ')
    

    Removes potential leading spaces from branch names.

  • Select and git checkout a commit (from history):

    git checkout $(git log --oneline --graph --decorate | fzf --preview 'git show --color=always {1}' --bind 'enter:execute-silent(git checkout {1})+abort' | cut -d ' ' -f 1)
    

    This is more advanced: previews commit details, allows checkout, and extracts the commit hash. {1} refers to the first field (commit hash).

  • Search terminal command history and execute:

    # Add this to your .bashrc or .zshrc
    bind '"\C-r": "!fzf --no-clear --bind=ctrl-r:abort --bind=enter:execute-print --preview=\"echo {1} | cut -d: -f2-\" | sed \"s/^ *//\""'
    

    This replaces the default Ctrl+R history search with fzf, providing a fuzzy search interface. execute-print prints the selected command to stdout, which your shell then interprets.

  • Find and kill a process:

    ps aux | fzf --preview 'ps aux | grep -w {1}' --multi --bind 'enter:execute-silent(kill -9 {2})+abort'
    

    Lists processes, allows previewing details, and uses Enter to kill the selected process. {2} refers to the second field (PID).

  • Select multiple files and pipe to a command:

    ls *.txt | fzf --multi --print0 | xargs -0 wc -l
    

    Selects multiple .txt files and counts the lines in each using wc -l.

Gotchas

  • Filenames with Spaces: When piping to commands that don’t handle null delimiters well (like rm without xargs -0), filenames with spaces can cause issues. Use --print0 | xargs -0 for safety.
  • Default find behavior: Without FZF_DEFAULT_COMMAND or input, fzf defaults to find .. This can be slow in very large directories. You might want to set FZF_DEFAULT_COMMAND to something more efficient like fd if you have it installed (fd --type f).
  • Shell Integration: The key bindings and auto-completion (Ctrl+T for files, ** for directories) are often installed separately via the install script (~/.fzf/install). Make sure you run this script and source the output in your shell configuration file.
  • Preview Command Errors: If your --preview command fails or produces no output, the preview window might appear blank or show an error. Ensure the preview command works correctly for individual items.
  • Field Indexing: When using execute or execute-silent with commands that process structured output (like git log), remember that {n} refers to the nth field, and {1..} refers to all fields starting from the first. Use tools like awk or cut within the preview command if needed.
  • --bind vs. bind: The bind command is a shell built-in for key bindings. fzf uses --bind for its internal key bindings. Be careful not to confuse them.