Fuzzy Find in the Terminal to Edit
Fuzzy Find in the Terminal with fzf
In this post, I’ll share how I use fzf
to fuzzy find and open files in my Editor. I also have a post on how I use fzf
to speed up working with Git on the command line. I use Neovim for a terminal editor, so that’s what’s in the examples below, but any editor that can be opened from the command line would work. Feel free to skip to the final solution that I’m currently using.
As a software engineer, I spend a good amount of time in the terminal, and very often what I’m doing there is simply trying to quickly read or edit a file. Problem is, in many of the projects that I’m working on, there’s a pretty sizeable folder structure to navigate. Even if it’s organized, it takes a while to navigate and get to where I want to go.
Enter fzf. This handy little command line tool fuzzy finds anything being fed to it, and then returns the results. This sounds pretty academic, and maybe it is. The strength of fzf
is that you can combine it with almost anything.
For example, if you want to find something in a text file, for instance, you can feed stuff into it like this cat myFile.txt | fzf
. This presents you with a prompt and real-time matches in a drop-down list; selecting any of these will return that line. Yes, you could also grep this, e.g. cat myFile.txt | grep mySearchTerm
. But that isn’t a dynamic search: you’d have to run the command again if you didn’t find what you were looking for. It’s also not case insensitive, meaning you’d have to pass -i
if you weren’t sure about capitalization, whereas fzf
does that by default. And, of course, fzf
uses fuzzy find, so you can skip a few letters and still hit your mark.
Setting up Fuzzy Finding and Automatically Opening Files in Neovim
The thing that I probably do most often, except for Git commands, is use fzf
with fd to quickly find and open files in Neovim
. I got the idea from Elijah Manson’s blog, but I don’t need tmux
for my current workflow, so I adapted it a bit. The basic idea goes like this: fd
everything, fuzzy find within the result, and open the selection in Neovim (the --type f
flag tells fd
to only look at files, not directories etc.):
1
fd --type f | fzf | xargs nvim
I added this to oh-my-zsh
as a custom alias f
, so all I had to do was type f
+Enter. This worked for a while, but then I ran into a problem: I tried opening a file with a space in it’s name, e.g. Spaces between words.md
. Neovim happily opened three files, Spaces
, between
, and words.md
. I needed to pass the argument as a single string. So, after a bit of experimentation, I landed on this:
1
fd --type f | fzf | sed 's/\ /\\ /g' | xargs nvim
In the above, I use sed
to replace all the spaces with \
, that is a backslash and a space, so the terminal knows to escape the space (and treat it with the two words around it as a single “word”). But, the \
character itself needs to be escaped in the sed
argument, thus \\
. Finally, I want to do this for all spaces, so I pass /g
to make the replace global.
Solution
This worked on the command line, but not quite for the alias that I’m setting with oh-my-zsh
. There, I needed to escape the \
a second time to make it work. This was what finally ended up as my alias, and so far it’s been working well:
1
alias f="fd --type f | fzf | sed 's/\ /\\\ /g' | xargs nvim"
Of course, my Neovim setup uses fzf
under the hood, so once I’m in Neovim, it’s not a problem finding other files. I could even have opened Neovim and then started the search, but even this would add few keystrokes. So being able to fuzzy find files from the terminal and then immediately opening them in Neovim has been really helpful.