Matthew Bennett

Logo

I am a data scientist working on time series forecasting (using R and Python 3) at the London Ambulance Service NHS Trust. I earned my PhD in cognitive neuroscience at the University of Glasgow working with fmri data and neural networks. I favour linux machines, and working in the terminal with Vim as my editor of choice.

View my GitHub Profile

View my LinkedIn Profile

View my CV

Configuring FZF to search useful directories beyond the working directory

I use fzf both as a command line tool and from within Vim using the fzf.vim plugin. It makes finding (and opening) files intuitive, fast, and frees you from needing to remember their location or exact name. By default, fzf searches recursively within the current directory, which is often just what you want. If you need to search for a file in some directory beyond the current working directory you need to specify that path as an argument to fzf, after which it's business as usual (fzf will recursively search the specified directory).

The Problem

It always felt a shame to have to occasionally precisely specify a path in order to get a fuzzy search going... precisely specifying a path is the exact thing that fzf is supposed to unburden your from! My initial approach was to supply the home directory path and let fzf search everything, the home directory path can be specified in only a couple of characters so there's no real burden in that case.

The problem with doing this is that you end up searching a lot of directories which you know don't have the file you want. The main offenders were directories you end up with if you install say, anaconda3. The results would be swamped with thousands of internal files, with very long paths. The long paths tended to 'soak up' any letters I entered in the search, so it was difficult for fzf to filter them out.

The Solution

You can choose which searching tool fzf uses under the hood. The default is the standard linux find command, but you can also use fd, ripgrep or silver searcher. Apart from being a lot faster than the default find, these latter tools respect .ignore files (thanks to @timblacktu comment for pointing this out!). This means that fzf will skip any files or directories listed in a .ignore file. We can turn this feature to our advantage.

First, we install fd. If you run Ubuntu 19.04 (Disco Dingo) or newer, you can install the officially maintained package:

sudo apt install fd-find

If you use an older version of Ubuntu, you can download the latest .deb package from the release page and install it via:

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

Now we configure fzf to use fd by adding the following line in your .bashrc:

export FZF_DEFAULT_COMMAND="fdfind . $HOME"

If you're using an older version than Ubuntu 19.10, the above line needs to be modified like so:

export FZF_DEFAULT_COMMAND="fd . $HOME"

Now fzf will always search recursively from the home directory, and respect any .ignore files:

cd ~/
touch .ignore

I find that the list of directories that I might conceivably (~15) want to recursively search with fzf is shorter that the list of directories that I would never want searched. The total number of files in the directories I want searched is about 5000 or so - easily handled by fd.

In the .ignore file, I first list all my home directories, each followed by a '/':

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

Then below those, put the directories that you want to be searched, each preceded by a '!' and followed by a '/':

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

The '!' will 'cancel out' the previous ignore commands.

And there we have it. We can invoke fzf wherever we are in the file system and start typing vague things about the file(s) we have in mind and fzf will search in a set of predefined directories and find it with ease. This completely removes the barrier of thinking where a file might be and how precisely it was named.

N.B. I have noticed that, for some reason, a couple of subdirectories were not showing up in the fzf search, and so I explicitly created some '!path/to/missed/directory/' lines in this section...

N.B. You may be wondering "What if I find myself in an usual directory not on the list, and want to use fzf?". I had the same concern so I put a couple of aliases in my .bashrc that can toggle the above configuration on and off at will (be sure to use 'fdfind' for Ubuntu 19.10+, as disused above):

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

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

If you're using Vim to create the .ignore file, an easy way to get a list of all the directories in your home directory is the following command:

:.!ls ~/

Append a '/' to all lines by putting the cursor on the first directory in the list and entering the following command:

:.,$ norm A/

Similar to above, insert the '!' before each one by putting the cursor on the first directory in the list and entering the following command:

:.,$ norm I!
Using FZF to select files for any program or command >

back to home