Output Handling
fzf outputs the selected line(s) to standard output. How you capture and use that output determines the power of fzf in your workflows.
Single Selection
# Basic capture
selected=$(ls | fzf)
echo "You chose: $selected"
# Use directly in a command (command substitution)
nvim $(find . -type f -name "*.lua" | fzf)
cat $(ls /etc | fzf)
ssh $(grep -E "^Host " ~/.ssh/config | awk '{print $2}' | fzf)
If the selection contains spaces, always use quotes: nvim "$(find . | fzf)". The --print0 / --read0 flags handle filenames with newlines (rare but possible).
Multi-select Output (--multi)
With -m, each selected item is printed on its own line:
# Select multiple files, open all in vim
vim $(find . -type f | fzf -m)
# Select multiple, delete interactively
find . -name "*.bak" | fzf -m | while read -r file; do
rm -v "$file"
done
# Pipe multi-select output into xargs
find . -name "*.log" | fzf -m | xargs grep "ERROR"
Handling Spaces in Filenames
Option 1: Quote substitution
while IFS= read -r file; do
nvim "$file"
done < <(find . | fzf -m)
Option 2: Null-delimited
find . -print0 | fzf --read0 --print0 | xargs -0 cat
The --expect Flag — Capture Which Key Was Pressed
--expect lets you define alternative action keys. fzf then outputs the pressed key as the first line, your selection as the second:
# Define ctrl-v and ctrl-x as alternate keys
result=$(ls | fzf --expect=ctrl-v,ctrl-x)
key=$(head -1 <<< "$result")
file=$(tail -1 <<< "$result")
case "$key" in
ctrl-v) nvim "$file" ;; # open in vim
ctrl-x) xdg-open "$file" ;; # open with GUI app
*) cat "$file" ;; # default: print to terminal
done
This pattern lets a single fzf invocation trigger different actions.
--bind with execute vs become
Rather than capturing output and acting on it in the shell, you can trigger actions directly inside fzf using --bind:
# execute: run a command without leaving fzf
ls | fzf --bind "enter:execute(nvim {})"
# become: replace fzf process with the command (cleaner terminal)
ls | fzf --bind "enter:become(nvim {})"
# ctrl-v: open in vertical split (neovim server)
ls | fzf --bind "ctrl-v:execute(nvim -o {} &)"
The {} placeholder is replaced with the currently highlighted item.
--with-nth — Display Subset of Fields
Use --with-nth to show only some columns in fzf's list (while preserving the full line for output):
# ps aux has many columns — show only columns 1 and 11 (user and command)
ps aux | fzf --header-lines=1 --with-nth=1,11
# Show only column 2 (PID)
ps aux | fzf --with-nth=2
--nth — Search Only Specific Fields
Limit which fields fzf fuzzy-matches against:
# Only search column 2 (PID) in ps output
ps aux | fzf --nth=2
# Only search columns 2 and 3 (leave user column unsearchable)
ps aux | fzf --nth=2,3
Using --delimiter
Change the field separator for --nth and --with-nth:
# Colon-separated: search only field 1 (before first colon)
cat /etc/passwd | fzf -d: --nth=1
# Tab-separated
cat data.tsv | fzf -d$'\t' --with-nth=1,3
Output with Context: --print-query
Print the query string as the first line of output (before the selection):
result=$(ls | fzf --print-query)
query=$(head -1 <<< "$result")
selection=$(tail -1 <<< "$result")
echo "Query: $query → Selected: $selection"
Useful when the query itself is semantically meaningful (e.g., typed a hostname that isn't in the list yet).