Как запустить fzf из другого каталога в текущем рабочем каталоге?

Я часто использую для навигации по файловой системе, особенно привязку клавиш Alt-c.

При вызове генерирует список из текущего рабочего каталога.

Можно ли сделать fzf создать список из указанного каталога?

я пытался fzf <dir>, но это приводит к ошибке (неизвестный вариант). Кроме того, я не могу найти такие варианты, как -C <dir> для указания начального каталога.

4 ответа

Решение

У меня возникла более общая проблема, которая может быть вам полезна. Следующее - из в сообщенияблоге, которое я написал об этом:

Настройка FZF для поиска полезных каталогов за пределами рабочего каталога

Я использую fzf как инструмент командной строки, так и из Vim с помощью плагина fzf.vim. Это делает поиск (и открытие) файлов интуитивно понятным, быстрым и избавляет вас от необходимости запоминать их местоположение или точное имя. По умолчанию fzf выполняет рекурсивный поиск в текущем каталоге, что часто бывает именно тем, что вам нужно. Если вам нужно найти файл в каком-либо каталоге за пределами текущего рабочего каталога, вам необходимо указать этот путь в качестве аргумента для fzf, после чего все будет как обычно (fzf будет рекурсивно искать указанный каталог).

Проблема

Всегда было стыдно, что время от времени приходится точно указывать путь, чтобы получить нечеткий поиск ... точное указание пути - это именно та вещь, от которой fzf должен избавить вас от бремени! Мой первоначальный подход заключался в том, чтобы указать путь к домашнему каталогу и позволить fzf искать все, путь к домашнему каталогу можно указать только с помощью пары символов, поэтому в этом случае нет реальной нагрузки.

Проблема с этим заключается в том, что вы в конечном итоге ищете множество каталогов, в которых, как вы знаете, нет нужного вам файла. Основными нарушителями были каталоги, в которых вы оказались, скажем, при установке anaconda3. Результаты будут завалены тысячами внутренних файлов с очень длинными путями. Длинные пути имели тенденцию «впитывать» любые буквы, которые я ввел при поиске, поэтому fzf было трудно их отфильтровать.

Решение

Вы можете выбрать, какой инструмент поиска будет использовать fzf. По умолчанию используется стандартная команда поиска linux, но вы также можете использовать fd, ripgrep или silver search. Помимо того, что эти последние инструменты намного быстрее, чем поиск по умолчанию, они учитывают файлы .gitignore. Это означает, что fzf пропустит любые файлы или каталоги, перечисленные в файле .gitignore. Мы можем использовать эту функцию в наших интересах.

Сначала мы устанавливаем fd. Если вы используете Ubuntu 19.04 (Disco Dingo) или новее, вы можете установить официально поддерживаемый пакет:

      sudo apt install fd-find

Если вы используете старую версию Ubuntu, вы можете загрузить последний пакет .deb со страницы выпуска и установить его через:

      # adapt version number and architecture
sudo dpkg -i fd_8.2.1_amd64.deb

Теперь мы настраиваем fzf для использования fd, добавляя следующую строку в ваш .bashrc:

      export FZF_DEFAULT_COMMAND="fdfind . $HOME"

Если вы используете более старую версию, чем Ubuntu 19.10, приведенную выше строку необходимо изменить следующим образом:

      export FZF_DEFAULT_COMMAND="fd . $HOME"

Теперь fzf всегда будет выполнять рекурсивный поиск из домашнего каталога и уважать любые файлы .gitignore в любом репозитории git. fzf обнаруживает репозитории git, ища каталог .git. Мы можем запустить это поведение в нашем домашнем каталоге, создав каталог .git. Для этого ваш домашний каталог не должен быть репозиторием git, но я не думаю, что кто-то это делает ... Затем мы можем создать файл .gitignore, чтобы игнорировать любые каталоги, которые мы хотим, то есть те, которые забивают наши поисковые запросы:

      cd ~/
mkdir .git
touch .gitignore

Я обнаружил, что список каталогов, в которых я мог бы (~ 15) захотеть рекурсивно искать с помощью fzf, короче, чем список каталогов, в которых я бы никогда не хотел искать. Общее количество файлов в каталогах, которые я хочу найти, составляет около 5000 или около того, что легко обрабатывается с помощью fd.

В файле .gitignore я сначала перечисляю все мои домашние каталоги, за каждым из которых следует '/':

      # start by igoring every home directory
anaconda3/
arch/
cache/
code/
Desktop/
  .
  .
  .

Затем под ними поместите каталоги, в которых нужно выполнить поиск, перед каждым из них стоит знак «!». и за которым следует '/':

      # now un-ignore the ones I care about
!code/
!Desktop/
!documents/
!downloads/
  .
  .
  .

Символ '!' "отменит" предыдущие команды игнорирования.

И вот оно. Мы можем вызвать fzf, где бы мы ни находились в файловой системе, и начать вводить неопределенные сведения о файлах, которые мы имеем в виду, а fzf будет искать в наборе предопределенных каталогов и легко находить его. Это полностью устраняет препятствия на пути к размышлениям о том, где может находиться файл и как точно он был назван.

NB Я заметил, что по какой-то причине несколько подкаталогов не отображались в поиске fzf, поэтому я явно создал несколько строк '! Path / to / missed / directory /' в этом разделе ...

NB. Вы можете спросить: «Что, если я окажусь в обычном каталоге, которого нет в списке, и захочу использовать fzf?». У меня была такая же проблема, поэтому я поместил пару псевдонимов в свой .bashrc, которые могут включать и выключать указанную выше конфигурацию по желанию (обязательно используйте fdfind для Ubuntu 19.10+, как не использовалось выше):

      # restore fzf default options ('fzf clear')
alias fzfcl="export FZF_DEFAULT_COMMAND=''"

# reinstate fzf custom options ('fzf-' as in 'cd -' as in 'back to where I was')
alias fzf-="export FZF_DEFAULT_COMMAND='fd . $HOME'"

Если вы используете Vim для создания файла .gitignore, простой способ получить список всех каталогов в вашем домашнем каталоге - это следующая команда:

      :.!ls ~/

Добавьте '/' ко всем строкам, поместив курсор в первый каталог в списке и введя следующую команду:

      :.,$ norm A/

Как и выше, вставьте '!' перед каждым, поместив курсор в первый каталог в списке и введя следующую команду:

      :.,$ norm I!

Вы можете сделать что-то вроде:

  • find <dir> | fzf
  • fd . <dir> | fzf

Источник.

Предполагая, что вы используете bash или аналогичный, он встроен в параметры завершения по умолчанию, которые устанавливаются с помощью fzf: https://github.com/junegunn/fzf#fuzzy-completion-for-bash-and-zsh

tldr; введите начальный файл или каталог, добавьте ** и ударил Tab. Итак, если вы войдете cd /foo/** затем вкладка открывает fzf с / foo в качестве начального каталога.

user14467607 работает блестяще!

С помощью приведенной ниже функции вы можете игнорировать настройку поведения с помощью fzfcl/fzf- и напрямую указывать путь в качестве аргумента fzf:

      fzf () {
    fzf_binary=$(unset -f fzf && which fzf)
    # is path provided
    if [[ "$1" != "" && -d $1 ]]
    then
            export FZF_DEFAULT_COMMAND="fd . $1"
    else
            export FZF_DEFAULT_COMMAND='fd . $HOME'
    fi
    $fzf_binary
}

Например, если вы хотите, чтобы fzf выполнял поиск, начиная с определенного каталога, вы можете выполнить:

      # current dir
fzf .
# or another dir:
fzf <path>

Если аргумент не указан, он будет выполняться в каталоге $HOME в соответствии с правилами .ignore:

      # this executes in $HOME:
fzf

!Отказ от ответственности:
если fzf используется в других инструментах/скриптах, которые могут вызывать эту функцию, возможно, не стоит перезаписывать имя fzf этой функцией.

Другие вопросы по тегам