Post

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.

This post is licensed under CC BY 4.0 by the author.