Разработчики ПО — если не единственные, то практически единственные, кому очень просто создавать инструменты для улучшения своей профессиональной работы; однако со временем это усложняет жизнь людям, постоянно переключающимся между разными инструментами и не вкладывающим время в глубокое изучение своего инструментария. Имея глубокое уважение к негласным знаниям людей лучше меня, я всё же считаю, что отличная эвристика 80/20 заключается в том, чтобы изучать старые добрые инструменты Unix
cat
, ls
, cd
, grep
и cut
. (а если вам повезло устроиться на должность настоящего современного сисадмина, то ещё и sed
с awk
.)Однако существуют инструменты, выгода от использования которых настолько мгновенна и ценность от применения настолько уникальна, что эвристика 80/20 полностью к ним неприменима. Один из них — это
fzf
. И меня очень печалит то, что многие скачивают его, запускают в командной строке «как есть», а потом просто мотают головой и произносят: «Я не понимаю».Мне хотелось бы изменить ситуацию. Предположим, что вы работаете на более-менее стандартной машине с Ubuntu. Вы только что установили
fzf
при помощи стандартного скрипта установки. Что же дальше?Сначала попробуйте Ctrl+R…
В большинстве терминалов, как в Linux, так и в Windows
Ctrl+R
позволяет выполнять поиск в обратном порядке введённых команд. Возможно вы, как и я, не слышали об этом до сего момента, несмотря на то, что работаете с шеллом уже десяток лет; причина в том, что базовая версия этого ПО неудобна по двум причинам:- Чтобы получить то, что вы пытаетесь вспомнить, нужно ввести полностью совпадающую строку.
- Вы получаете только одно превью, поэтому если ошибётесь в полностью совпадающей строке хотя бы на один символ, придётся искать ветра в поле.
fzf
— довольно странная программа, потому что её установка полностью перезаписывает целую кучу горячих клавиш, чтобы сделать их лучше. В обычной ситуации мне бы это не понравилось. Но…… Это существенное улучшение по сравнению с тем, что было.
(Стоит заметить, что установка
fzf
через менеджер пакетов наподобие apt
может и не дать такого результата! Именно поэтому я продолжаю намекать, что следует использовать скрипт установки, даже если вы согласны со мной в том, что curl | bash
— это зло!)… а теперь попробуйте Alt+C
Допустим, вы запускаете пустой терминал. Вы пытаетесь быстро найти свои репозитории хобби-проектов и перейти к ним с помощью
cd
, но вы уже несколько недель не работали с ними, потому что ваша основная работа необычайно интересна и увлекательна… Как их найти?Ответ: с помощью
fzf
. fzf
превращает Alt+C
в сочетание горячих клавиш для тюнингованного cd
с нечётким поиском и позволяет очень быстро перемещаться, когда единственное, что вы смутно помните — имя нужной папки.Основная команда fzf
Итак, мы разобрались с горячими клавишами. Откровенно говоря, эти две функции сами по себе представляют основную ценность, получаемую мной от
fzf
, но давайте всё-таки посмотрим, что делает сама эта команда.Она выполняет нечёткий поиск местоположений файлов! По крайней мере, относительно вашей собственной папки. Само по себе это не особо полезно.
Но попробуйте vi $(fzf), и вуаля…!
Вы получаете возможность нечёткого поиска в редакторе!
(Кстати, в данном случае в
vi
нет ничего уникального. Можно вызывать команду с emacs
, nano
, code
и любым другим редактором!)vi $(find. '/' | fzf): для поиска произвольных файлов конфигурации
Однажды я попытался создать свою первую автоматическую перезагрузку при помощи расширения Firefox,
entr
и nginx
. И у меня возник вопрос: где же находится nginx.conf
?Я составил список возможных действий. Можно было:
- Воспользоваться полузабытыми знаниями FHS, чтобы попытаться угадать при помощи
trees
иgrep
, или - Просто крепко запомнить местонахождение и ощущать своё превосходство над всеми остальными, или
- Присоединить пайпом
find
. ‘/’ кfzf
и начать поиск.
Мне очень нравится этот клип, потому что в нём показаны некоторые тонкости использования
fzf
, а также одна из наиболее продвинутых функций поиска — поиск conf$
отфильтровывает все строки, которые не заканчиваются на conf
. Обратите внимание, что fzf
временно сходит с ума, когда find
сталкивается с кучей ошибок «Permission denied», но спустя несколько секунд приходит в себя.Стоят ли платить этими лишними секундами за возможность нахождения файлов конфигурации таким не требующим мыслительных усилий способом? На мой взгляд, да.
Ещё меньше проблем: vi **<TAB>
Спасибо sigmonsays за то, что напомнил мне об этой возможности!
Примерно посередине спектра между «перезаписать сочетания горячих клавиш» и «использовать стандартный fzf» находится «использовать две звёздочки для нечёткого автозаполнения отступов». Вот пример того, как я применяю это для выполнения чего-то похожего на
vi $(fzf)
:После получения команды всё-таки придётся ещё раз нажать на
Enter
.У меня пока не появилось привычки использовать это часто, потому что в реальной жизни это пригождается мне дома только как замена
$(fzf)
, а вызов явным образом мне запомнить намного проще. Думаю, для любителей tab-tab-звёздочки это похоже на то, как мой коллега копипастит вручную из терминала, вместо того, чтобы воспользоваться :read ! echo "Hello world!"
.mv $(fzf) $(fzf) — для реально страдающих амнезией
Для случаев, когда вы не помните точно, ни куда вы выполнили перемещение, ни что переместили, но понимаете, что это точно было сделано.
Знакомство с rg: с быстрым и рекурсивным по умолчанию grep
Всё, что описано ниже, можно выполнить и при помощи
grep
, однако истинные возможности rg
(также называемого ripgrep
) раскрывает его рекурсивная по умолчанию природа. Крайне рекомендую скачать его и использовать в показанных ниже примерах. Но если вы боитесь новых инструментов, то не стоит волноваться!rg . | fzf
: нечёткий поиск каждой строки в каждом файлеИтак, теперь мы зашли на территорию настоящей амнезии.
rg . | fzf | cut -d ":" -f 1
: нечёткий поиск каждой строки в каждом файле и возврат местоположения файлаvim $(rg . | fzf | cut -d ":" -f 1)
: нечёткий поиск каждой строки в каждом файле и открытие этого файлаКомментарии (23)
unC0Rr
31.07.2023 07:45+4mv $(fzf) $(fzf) — для реально страдающих амнезией
Учитывая, что останется в .history — именно так всегда и будет: "что-то куда-то перемещено".
Для случаев, когда вы не помните точно, ни куда вы выполнили перемещение, ни что переместили, но понимаете, что это точно было сделано.baldr
31.07.2023 07:45Кстати, а fzf ищет по .history или еще по какой-то своей базе? Есть же известная проблема с несколькими терминалами - в history по-умолчанию записывается история только последнего закрытого терминала. У меня постоянно открыто около 20 вкладок терминала, поэтому полагаться можно только на недавнюю историю.
Cheater
31.07.2023 07:45+2Fzf не имеет своей БД/индекса поиска, это интерфейс навигации по набору строк, подаваемых ему на вход. По умолчанию например, если его вызывать без аргументов, он вызывает дочерним процессом find и обрабатывает его вывод. Локальную историю соответственно ему тоже можно отдать вызовом правильной утилиты ("fc -lI" в zsh например).
iLi0ni
31.07.2023 07:45+1Разве это не решает проблему?:
shopt -s histappend
PROMPT_COMMAND='history -a'
baldr
31.07.2023 07:45+2Да, но решает опять немного не так как хотелось бы. При нажатии стрелки вверх оно же покажет последнюю команду среди всех окон, а не только текущего?
Мне нужно чтобы и история не пропадала, но чтобы быстрый поиск использовал, в первую очередь, историю текущего окна.
LF69ssop
31.07.2023 07:45+11Очень странные примеры откровенно говоря, скорее приводящие в ужас чем вызывающие желание подобный пакет установить.
"Выгода и ценность" после прочтения остались под большим вопросом. Классические инструменты как-то удобнее, и притом они есть везде.
xotkot
31.07.2023 07:45+1если искать по строкам то и открывать файл лучше уж сразу на нужной строке:
rg -n . | fzf | awk -F: '{print "+"$2,$1}'
для редактора emacs:
emacs $(rg -n . | fzf | awk -F: '{print "+"$2,$1}')
для alias:
alias ff='emacs $(rg -n . | fzf | awk -F: '\''{print "+"$2,$1}'\'')'
PeterFukuyama
31.07.2023 07:45+2FZF_DEFAULT_OPTS=--preview="head {} -n 100"
Добавление предпросмотра при поиске.
brake
31.07.2023 07:45+1На серверах, скорее всего, будет только стандартный набор команд и никто не позволит ставить там всё описанное выше. Так зачем привыкать?
saidelman
31.07.2023 07:45+3Затем, чтобы было удобно хотя бы локально. Мало кто ведь локально работает в голом vim версии 2008 года? Или в nano. А на серверах только они и будут, скорее всего.
А ещё далеко не всем нужно ходить на сервера, на которых нельзя ничего ставить. Кому-то можно устанавливать свой софт, а кому-то вообще все эти удалённые сервера нужны раз в тысячелетие.
baldr
За перевод спасибо.
Однако, например, для поиска файлов по всему диску все же удобнее пользоваться mlocate, на мой взгляд. find каждый раз начинает поиск сначала и долго пробегается по всем папкам, а locate хранит весь список в свой базе (правда, обновляет ее только раз-два в день). Поэтому когда делаешь find + grep, а потом осознаешь что надо бы еще пару раз применить grep чтобы сократить список - немного раздражает снова ждать полного пересканирования диска.
iDoka
Вы можете принудительно вызывать обновление, после значительного обновления содержимого ФС:
sudo updatedb
на SSD ext4 обновление занимаем буквально секунды
baldr
Именно так и делаю. Я уж не стал это писать.
mpa4b
А зачeм делать find и потом греп, если у первого есть достаточный набор фильтров, по имени файла в том числе. Мне в голову приходит только find с опцией -exec (ну или далее xargs), где грепом ищется что-то внутри файлов.
baldr
Ну вот мне быстрее вспомнить "locate | grep amqplib" чем все ключи у find. А потом надо повторить поиск, но добавив ещё условий, а find работает гораздо медленнее.
orbion
У find есть многопоточная (и более дружелюбная, как позиционирует автор) альтернатива – fd, можно найти в репозиториях многих дистрибутивов. От медленного диска, конечно, не спасёт, но работает порой ощутимо быстрее.
Vaitek
А для быстрого поиска на подмонтированных NFS поможет?