fzf: интерактивный поиск в терминале macOS

Если вы проводите много времени в терминале, то наверняка знаете это чувство: нужно найти файл, вспомнить команду из истории или переключиться на нужную ветку Git. Обычно это означает много набора текста, grep, find и прочих команд. fzf — инструмент, который превращает эти рутинные задачи в быстрый интерактивный поиск.
Что такое fzf?
fzf (fuzzy finder) — это универсальный инструмент для "нечёткого" поиска в командной строке. Он принимает любой список строк и позволяет мгновенно фильтровать его по мере набора текста.
Ключевые особенности:
- Fuzzy-поиск — не нужно помнить точное название, достаточно нескольких букв в любом порядке
- Мгновенная фильтрация — результаты обновляются при каждом нажатии клавиши
- Универсальность — работает с любым текстовым вводом (файлы, история, процессы, ветки Git и т.д.)
- Интеграция — встраивается в bash, zsh, fish и другие оболочки
- Лёгкий — написан на Go, работает молниеносно даже с огромными списками
Пример "нечёткого" поиска
Допустим, вы ищете файл UserAuthenticationController.ts. С fzf достаточно набрать:
uac— найдёт по первым буквам словauthcon— найдёт по части словcontroller user— порядок не важен
fzf находит все строки, содержащие введённые символы в любом порядке, и ранжирует их по релевантности.
Установка fzf на macOS
Самый простой способ — через Homebrew:
brew install fzf
После установки запустите скрипт настройки для интеграции с вашей оболочкой:
# Установит полезные key bindings и автодополнение
$(brew --prefix)/opt/fzf/install
Скрипт спросит:
- Enable fuzzy auto-completion? — да, это добавит автодополнение с fzf
- Enable key bindings? — да, это добавит горячие клавиши (Ctrl+R, Ctrl+T и др.)
- Update shell config? — да, добавит нужные строки в
.bashrcили.zshrc
После установки перезапустите терминал или выполните:
source ~/.zshrc # или ~/.bashrc
Проверка установки:
fzf --version
# 0.54.3 (brew)
Базовое использование
Поиск файлов
Просто запустите fzf в любой директории:
fzf
Это откроет интерактивный список всех файлов в текущей директории и поддиректориях. Начните набирать — список будет фильтроваться в реальном времени.
Управление:
| Клавиша | Действие |
|---|---|
↑ / ↓ | Перемещение по списку |
Enter | Выбрать и вывести результат |
Esc / Ctrl+C | Отмена |
Tab | Выбрать несколько (в режиме multi-select) |
Ctrl+J / Ctrl+K | Альтернатива стрелкам |
Передача данных через pipe
fzf работает с любым списком строк:
# Найти процесс
ps aux | fzf
# Найти установленный brew-пакет
brew list | fzf
# Выбрать ветку Git
git branch | fzf
Использование результата
Результат fzf можно подставить в другую команду:
# Открыть выбранный файл в VS Code
code $(fzf)
# Удалить выбранный файл (осторожно!)
rm $(fzf)
# Перейти в выбранную директорию
cd $(find . -type d | fzf)
Горячие клавиши в терминале
После установки key bindings появляются три мощные комбинации:
Ctrl+R — поиск по истории команд
Это, пожалуй, самая полезная функция. Вместо стандартного Ctrl+R, который показывает команды по одной, fzf показывает всю историю с интерактивным поиском.
# Нажмите Ctrl+R и начните вводить
# Например: "docker" — покажет все команды с docker
# Или: "npm run" — все npm run команды
Преимущества:
- Видно сразу много результатов
- Нечёткий поиск:
gcoнайдётgit checkout - Можно искать по любой части команды
Ctrl+T — вставка пути к файлу
Находясь в середине набора команды, нажмите Ctrl+T чтобы найти и вставить путь к файлу:
# Набираете команду:
vim <нажимаете Ctrl+T>
# Открывается fzf, выбираете файл
# Путь автоматически вставляется:
vim src/components/Header.vue
Alt+C (или Esc+C на macOS) — переход в директорию
Мгновенный поиск и переход в любую поддиректорию:
# Нажмите Alt+C (или Esc, затем C)
# Выберите директорию — cd выполнится автоматически
Примечание для macOS: По умолчанию
Altв Terminal.app работает иначе. Либо используйтеEsc+C(нажать Esc, отпустить, нажать C), либо настройте терминал на использование Option как Meta.
Продвинутые возможности
Превью файлов
fzf может показывать содержимое файла прямо в окне поиска:
fzf --preview 'cat {}'
Для более красивого превью с подсветкой синтаксиса установите bat:
brew install bat
# Теперь превью будет с подсветкой
fzf --preview 'bat --color=always --style=numbers --line-range=:500 {}'
Настройка превью по умолчанию (добавить в .zshrc)
# Красивое превью с bat (если установлен) или cat
export FZF_DEFAULT_OPTS="--preview 'bat --color=always --style=numbers --line-range=:500 {} 2>/dev/null || cat {}'"
# Настройка высоты окна превью (50% справа)
export FZF_DEFAULT_OPTS="$FZF_DEFAULT_OPTS --preview-window=right:50%:wrap"
Множественный выбор
Флаг -m или --multi позволяет выбрать несколько элементов с помощью Tab:
# Выбрать несколько файлов для удаления
rm $(fzf -m)
# Выбрать несколько файлов для git add
git add $(fzf -m)
Выбор директорий
По умолчанию fzf ищет файлы. Для поиска только директорий:
# Найти и перейти в директорию
cd $(find . -type d | fzf)
# Или создать алиас
alias cdf='cd $(find . -type d | fzf)'
Превью директорий с tree
Команда tree показывает структуру директории в виде дерева — это идеальный инструмент для превью папок в fzf.
Установка tree:
brew install tree
Основные флаги tree:
| Флаг | Описание |
|---|---|
-C | Цветной вывод |
-L N | Глубина вложенности (например, -L 2) |
-a | Показывать скрытые файлы |
-d | Только директории |
-I pattern | Игнорировать файлы по паттерну |
Использование с fzf:
# Выбор директории с превью структуры
cd $(find . -type d | fzf --preview 'tree -C -L 2 {}')
Функция для навигации с tree-превью
# Добавьте в .zshrc
ftree() {
local dir
dir=$(find ${1:-.} -type d 2>/dev/null | fzf --preview 'tree -C -L 2 {} 2>/dev/null' --preview-window=right:50%)
[[ -n "$dir" ]] && cd "$dir"
}
# Или с fd (быстрее)
ftree() {
local dir
dir=$(fd --type d --hidden --exclude .git 2>/dev/null | fzf --preview 'tree -C -L 2 {} 2>/dev/null' --preview-window=right:50%)
[[ -n "$dir" ]] && cd "$dir"
}
Теперь при выборе директории вы сразу видите её содержимое в виде дерева — это значительно упрощает навигацию по незнакомым проектам.
Кастомные команды для генерации списка
Переменная FZF_DEFAULT_COMMAND определяет, откуда fzf берёт список файлов по умолчанию.
Рекомендуемые настройки с fd (современная замена find)
Сначала установите fd — быструю замену find:
brew install fd
Затем добавьте в .zshrc:
# Использовать fd вместо find (быстрее, уважает .gitignore)
export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'
# Для Ctrl+T тоже использовать fd
export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND"
# Для Alt+C (поиск директорий)
export FZF_ALT_C_COMMAND='fd --type d --hidden --follow --exclude .git'
Преимущества fd:
- В 5-10 раз быстрее find
- Автоматически игнорирует файлы из
.gitignore - Более понятный синтаксис
Интеграция с Git
fzf отлично работает с Git. Вот несколько полезных алиасов и функций:
Git-функции для .zshrc
# Переключение веток через fzf
gco() {
local branch
branch=$(git branch --all | grep -v HEAD | sed 's/.* //' | sed 's#remotes/origin/##' | sort -u | fzf --height 40% --reverse)
if [[ -n "$branch" ]]; then
git checkout "$branch"
fi
}
# Интерактивный git log с превью коммитов
glog() {
git log --oneline --color=always | fzf --ansi --preview 'git show --color=always {1}' --preview-window=right:60%
}
# Выбор файлов из git status для git add
gadd() {
local files
files=$(git status --short | fzf -m --preview 'git diff --color=always {2}' | awk '{print $2}')
if [[ -n "$files" ]]; then
echo "$files" | xargs git add
git status --short
fi
}
# Удаление локальных веток
gbr-delete() {
local branches
branches=$(git branch | grep -v '\*' | fzf -m)
if [[ -n "$branches" ]]; then
echo "$branches" | xargs git branch -d
fi
}
# Интерактивный git stash
gstash() {
local stash
stash=$(git stash list | fzf --preview 'git stash show -p {1}' | cut -d: -f1)
if [[ -n "$stash" ]]; then
git stash apply "$stash"
fi
}
Использование:
gco— выбрать и переключиться на веткуglog— просмотр истории с превьюgadd— интерактивныйgit addс просмотром diffgbr-delete— удаление локальных ветокgstash— применение stash
Интеграция с другими инструментами
npm scripts
Интерактивный запуск npm-скриптов:
Функция для запуска npm scripts
# Добавьте в .zshrc
nr() {
local script
script=$(cat package.json | jq -r '.scripts | keys[]' 2>/dev/null | fzf --height 40% --reverse)
if [[ -n "$script" ]]; then
echo "Running: npm run $script"
npm run "$script"
fi
}
Теперь просто введите nr в проекте с package.json и выберите скрипт.
Docker
Docker-функции для fzf
# Остановить контейнер
dstop() {
local container
container=$(docker ps --format '{{.Names}}\t{{.Image}}\t{{.Status}}' | fzf | awk '{print $1}')
if [[ -n "$container" ]]; then
docker stop "$container"
fi
}
# Посмотреть логи контейнера
dlogs() {
local container
container=$(docker ps --format '{{.Names}}\t{{.Image}}' | fzf | awk '{print $1}')
if [[ -n "$container" ]]; then
docker logs -f "$container"
fi
}
# Зайти в контейнер
dexec() {
local container
container=$(docker ps --format '{{.Names}}\t{{.Image}}' | fzf | awk '{print $1}')
if [[ -n "$container" ]]; then
docker exec -it "$container" sh
fi
}
# Удалить образы
drmi() {
local images
images=$(docker images --format '{{.Repository}}:{{.Tag}}\t{{.Size}}' | fzf -m | awk '{print $1}')
if [[ -n "$images" ]]; then
echo "$images" | xargs docker rmi
fi
}
SSH-хосты
Быстрое подключение к SSH-хостам
# Добавьте в .zshrc
fssh() {
local host
host=$(grep "^Host " ~/.ssh/config | awk '{print $2}' | fzf --height 40% --reverse)
if [[ -n "$host" ]]; then
ssh "$host"
fi
}
Теперь fssh покажет все хосты из ~/.ssh/config и подключится к выбранному.
Kill процесса
Интерактивное завершение процессов
# Добавьте в .zshrc
fkill() {
local pid
pid=$(ps -ef | sed 1d | fzf -m --preview 'echo {}' | awk '{print $2}')
if [[ -n "$pid" ]]; then
echo "$pid" | xargs kill -9
fi
}
Полная конфигурация
Рекомендуемая конфигурация fzf для .zshrc
# ==========================================
# FZF Configuration
# ==========================================
# Использовать fd для поиска (быстрее find, уважает .gitignore)
# Если fd не установлен, fzf использует стандартный find
if command -v fd &> /dev/null; then
export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'
export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND"
export FZF_ALT_C_COMMAND='fd --type d --hidden --follow --exclude .git'
fi
# Внешний вид и поведение fzf
export FZF_DEFAULT_OPTS="
--height 60%
--layout=reverse
--border rounded
--info=inline
--margin=1
--padding=1
"
# Превью файлов (использует bat если установлен)
if command -v bat &> /dev/null; then
export FZF_DEFAULT_OPTS="$FZF_DEFAULT_OPTS --preview 'bat --color=always --style=numbers --line-range=:300 {} 2>/dev/null || cat {}' --preview-window=right:50%:wrap"
fi
# Цветовая схема (опционально — настройте под свой терминал)
# export FZF_DEFAULT_OPTS="$FZF_DEFAULT_OPTS
# --color=fg:#c0caf5,bg:#1a1b26,hl:#bb9af7
# --color=fg+:#c0caf5,bg+:#292e42,hl+:#7dcfff
# --color=info:#7aa2f7,prompt:#7dcfff,pointer:#7dcfff
# --color=marker:#9ece6a,spinner:#9ece6a,header:#9ece6a
# "
# Настройка Ctrl+R (история команд)
export FZF_CTRL_R_OPTS="
--preview 'echo {}'
--preview-window=down:3:wrap
--bind 'ctrl-y:execute-silent(echo -n {2..} | pbcopy)+abort'
--header 'Press CTRL-Y to copy command to clipboard'
"
# Настройка Ctrl+T (вставка пути файла)
export FZF_CTRL_T_OPTS="
--preview 'bat --color=always --style=numbers --line-range=:300 {} 2>/dev/null || cat {}'
--preview-window=right:60%:wrap
--bind 'ctrl-/:toggle-preview'
"
# Настройка Alt+C (переход в директорию)
# Использует tree для красивого превью структуры (если установлен)
export FZF_ALT_C_OPTS="
--preview 'tree -C -L 2 {} 2>/dev/null || ls -la {}'
--preview-window=right:50%
"
# ==========================================
# Полезные алиасы и функции
# ==========================================
# Поиск и открытие файла в редакторе
fe() {
local file
file=$(fzf --query="$1" --select-1 --exit-0)
[[ -n "$file" ]] && ${EDITOR:-vim} "$file"
}
# Поиск и переход в директорию
fcd() {
local dir
dir=$(find ${1:-.} -type d 2>/dev/null | fzf +m)
[[ -n "$dir" ]] && cd "$dir"
}
# Поиск в содержимом файлов (требует ripgrep)
frg() {
if ! command -v rg &> /dev/null; then
echo "ripgrep (rg) is not installed. Install with: brew install ripgrep"
return 1
fi
local file line
read -r file line <<< $(rg --line-number --no-heading --color=always "${1:-}" | fzf --ansi | awk -F: '{print $1, $2}')
[[ -n "$file" ]] && ${EDITOR:-vim} "$file" +"$line"
}
# Git checkout branch
gco() {
local branch
branch=$(git branch --all | grep -v HEAD | sed 's/.* //' | sed 's#remotes/origin/##' | sort -u | fzf --height 40% --reverse)
[[ -n "$branch" ]] && git checkout "$branch"
}
# Git add с превью
gadd() {
local files
files=$(git status --short | fzf -m --preview 'git diff --color=always {2}' | awk '{print $2}')
[[ -n "$files" ]] && echo "$files" | xargs git add && git status --short
}
# npm run с выбором скрипта
nr() {
local script
script=$(cat package.json 2>/dev/null | jq -r '.scripts | keys[]' 2>/dev/null | fzf --height 40% --reverse)
[[ -n "$script" ]] && npm run "$script"
}
Частые проблемы и решения
Alt+C не работает на macOS
Проблема: Комбинация Alt+C не открывает fzf для выбора директории.
Причина: В Terminal.app и iTerm2 клавиша Alt (Option) по умолчанию используется для ввода специальных символов, а не как модификатор Meta.
Решения:
1. Использовать Esc+C:
Нажмите Esc, отпустите, затем нажмите C. Это эквивалент Alt+C.
2. Для iTerm2:
- Preferences → Profiles → Keys
- Установите "Left Option key" в "Esc+"
3. Для Terminal.app:
- Preferences → Profiles → Keyboard
- Включите "Use Option as Meta key"
fzf не находит файлы из .gitignore
Проблема: fzf пропускает некоторые файлы.
Причина: Если вы используете fd или rg как источник, они по умолчанию уважают .gitignore.
Решение:
# Показывать игнорируемые файлы
export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --no-ignore'
Поиск медленный в больших директориях
Проблема: fzf долго загружает список файлов.
Решение:
- Установите
fdвместо стандартногоfind:brew install fd export FZF_DEFAULT_COMMAND='fd --type f' - Исключите тяжёлые директории:
export FZF_DEFAULT_COMMAND='fd --type f --exclude node_modules --exclude .git --exclude vendor' - Используйте
--heightдля ограничения списка:fzf --height 40%
Превью не работает
Проблема: Окно превью показывает ошибку или пустое.
Решения:
- Проверьте наличие утилит:
# Для подсветки синтаксиса brew install bat # Для поиска по содержимому brew install ripgrep - Используйте простое превью:
export FZF_DEFAULT_OPTS="--preview 'cat {}'" - Отключите превью:
fzf --no-preview
Заключение
fzf — это инструмент, который кардинально меняет работу в терминале. После освоения вы удивитесь, как раньше обходились без него.
Рекомендуемый путь освоения:
- Начните с Ctrl+R — поиск по истории команд. Это самая частая операция, и вы сразу почувствуете пользу.
- Освойте Ctrl+T — вставка путей к файлам. Особенно полезно для
vim,code,catи подобных команд. - Добавьте Git-функции —
gcoдля переключения веток станет вашим новым любимым инструментом. - Настройте превью — установите
bat,fdиtreeдля лучшего опыта. - Создавайте свои функции — fzf универсален, его можно применить практически к любому списку данных.
Комментарии
Войдите, чтобы оставить комментарий
Пока нет комментариев. Будьте первым!