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:
fzfdoesn’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:
fzfpresents an interactive terminal interface where you type your query, and the results update in real-time. - Input Source:
fzfreads from standard input (stdin) to generate its list. This makes it incredibly versatile as you can pipe the output of almost any command intofzf. - Output: By default,
fzfprints the selected item(s) to standard output (stdout).
Commands / Usage
Basic Usage
-
Find files in the current directory and subdirectories:
fzfThis command, when run without input, uses
find .by default to list files. -
Find files from a specific directory:
find /path/to/directory | fzfLists files within
/path/to/directoryand its subdirectories. -
Select a command from history:
history | fzfSearches your shell history and prints the selected command.
-
Select a Git branch:
git branch | fzfLists 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=reversePuts the
fzfinterface at the bottom of the screen. -
--multi: Enable multi-selection (usingTabandShift+Tab).ls | fzf --multiAllows 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 rmSafely 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(acatclone 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 --exactOnly shows files whose names exactly match your input.
-
--case-sensitive: Enable case-sensitive matching.find . -type f | fzf --case-sensitivefile.txtwill not matchFILE.TXTunless you typeFILE.TXT. -
--word: Trigger fuzzy matching only for the current word.find . -type f | fzf --wordUseful when you have multiple words in your query.
-
--bind KEY:ACTION: Bind keys to specific actions.fzf --bind 'ctrl-o:execute(code {})'Pressing
Ctrl+Owhen 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
Enterappends the selected item toselected_files.txtwithout closingfzf.
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 closingfzf).find . -type f | fzf --bind 'ctrl-y:execute-silent(echo {} | pbcopy)'Copies the selected filename to the clipboard using
pbcopy(macOS). Usexclip -selection clipboardon Linux. -
accept: The default action when you pressEnter(prints the selection to stdout). -
abort: Exitfzfwithout printing a selection. -
toggle-preview: Show/hide the preview window.
Environment Variables
-
FZF_DEFAULT_COMMAND: The default command to execute whenfzfis run without input.# Set in your .bashrc or .zshrc export FZF_DEFAULT_COMMAND='find . -type f'This makes
fzfdefault to finding files. -
FZF_DEFAULT_OPTS: Default options forfzf.# Set in your .bashrc or .zshrc export FZF_DEFAULT_OPTS='--layout=reverse --height=50% --preview="bat --color=always {}"'Applies these options every time
fzfis run.
Common Patterns
-
Open any file with your default editor (e.g., Vim):
vim $(fzf)This is a very common and powerful pattern.
fzflists files, you select one, andvimopens 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
vconfigthat runs:vim $(find ~/.config ~/.* -type f | fzf --preview 'cat {}' --height 80%) -
Select and
git checkouta branch:git checkout $(git branch | fzf | tr -d ' ')Removes potential leading spaces from branch names.
-
Select and
git checkouta 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+Rhistory search withfzf, providing a fuzzy search interface.execute-printprints the selected command to stdout, which your shell then interprets. -
Find and
killa 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
Enterto 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 -lSelects multiple
.txtfiles and counts the lines in each usingwc -l.
Gotchas
- Filenames with Spaces: When piping to commands that don’t handle null delimiters well (like
rmwithoutxargs -0), filenames with spaces can cause issues. Use--print0 | xargs -0for safety. - Default
findbehavior: WithoutFZF_DEFAULT_COMMANDor input,fzfdefaults tofind .. This can be slow in very large directories. You might want to setFZF_DEFAULT_COMMANDto something more efficient likefdif you have it installed (fd --type f). - Shell Integration: The key bindings and auto-completion (
Ctrl+Tfor files,**for directories) are often installed separately via theinstallscript (~/.fzf/install). Make sure you run this script and source the output in your shell configuration file. - Preview Command Errors: If your
--previewcommand 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
executeorexecute-silentwith commands that process structured output (likegit log), remember that{n}refers to the nth field, and{1..}refers to all fields starting from the first. Use tools likeawkorcutwithin the preview command if needed. --bindvs.bind: Thebindcommand is a shell built-in for key bindings.fzfuses--bindfor its internal key bindings. Be careful not to confuse them.