Faster directory navigation with fzf

How a one-line command will help you improve your CLI workflow

Cowritten with Marian Molina August 14, 2021

Changing directories is something we do quite a lot when using the command-line. You’d agree that it’s slow to fill a target directory path even for a directory you visit often. The funny thing is that we repeat the same process every single time.

Well, if you use shell completion it will give you useful suggestions so no more guessing, but it’s still slow as you move from a directory to another one by one.

What if you could run a one-line command that would list all your directories, prompt you to type your target directory name, hit the Enter key to select it from the list and voila, you are now at your target directory! Feels different, isn’t it?

You’d be surprised how easy it is to compose such a command by combining cd with fzf, a general purpose command-line fuzzy finder. fzf provides a very fast interactive interface that can be used with any type of list.

So, what’s this one-line command? Let’s give it a look before explaining it in detail:

cd $(find * -type d | fzf)

Don’t worry if it doesn’t make sense just yet, it will soon become clearer. Let’s first break it down into three steps:

If you want to follow along, you can get fzf from this installation guide.

Listing directories

We first need to list the directories we want to search from. There are many tools to do that and for today we’ll use find as it’s usually already installed on most systems.

Let’s now see how to use it in action and take a look at its output :

find * -type d
files files/personal files/personal/photos files/personal/notes files/work files/work/notes files/work/docs

find lists the directories within your current directory recursively.

Here we used * as an argument to ignore the hidden directories, you could replace * with . to include all directories.

You’ve also noticed we used the -type d flag and that’s to tell find to search for only directories as it searches for both files and directories by default. So we have to specify that option to look only for directories.

Depending on your files structure, find output could vary from hundreds to thousands of directories. Hence, we need a tool to filter those results to the target directory. Here comes fzf.

Selecting directory

Once we have our list of directories we want to search for our target directory and select it.

To achieve that we just need to pipe the list of directories we got from find to fzf:

find * -type d | fzf
» | 7/7 (0) › files files/personal files/personal/photos files/personal/notes files/work files/work/notes files/work/docs

It doesn’t look so much different from what we saw with find output, but the cool thing is that now you can start typing and the list will be filtered to match your input.

If we are looking for notes/ directory for example, let’s type notes and see the list updating:

» notes 2/7 (0) › files/personal/notes files/work/notes

You can also go Up and Down with the arrow keys to navigate through the results and if you select a directory by hitting Enter, it’ll be printed to the console:


Almost there. Now we need to go to this directory.

Changing directory

Here comes the last part of our command, let’s take the result of fzf and pass it to cd:

cd $(find * -type d | fzf)

By typing notes then selecting its path as we did previously, the expression $(find * - type d | fzf) will be evaluated to files/personal/notes to become the argument of cd.

Here we are! Our current directory now changed to the selected directory.

Additional tips ⌁

I would recommend setting an alias to access this command quickly. It also makes sense to start searching from your home directory, hence cd ~.

# bash | zsh alias sd="cd ~ && cd \$(find * -type d | fzf)" # fish alias sd "cd ~ && cd (find * -type d | fzf)"

Here sd alias would stand for search directories and it’s similar to the good old cd command.

You could set this alias permanently by adding the line above to your shell configuration file i.e. .bashrc, .zshrc or depending on what you’re using.

If you want to ignore some directories with find you’ll need a flag with an ignore pattern, or you can replace find with fd or rg as a search tool with a global .ignore file. Both are very fast.

There are also some key bindings and widgets related to fzf that might not be installed by default. They enable you to change directories by pressing ATL-C or by running the command fzf-cd-widget.

What’s next

As you can see in case you work with hundreds or even thousands of directories, searching for a one directory with fzf would be much more efficient than just using cd.

I’m currently using fzf with nvim, npm scripts and git commands, shell scripts and basically anything I could think of to make my life easier. Let me know if you are interested to know more about some of those use cases.

What about you? I’m curious to know if you’ve used fzf before and how it fits in your current workflow. Or maybe you have some ideas to optimize your workflow with fzf?

Share this post if you find it useful and stay tuned for upcoming posts. If you have questions or got stuck at some point, leave a comment on the discussion and I’ll be happy to help.