Faster directory navigation with fzf
How a one-line command will help you improve your CLI workflow
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
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:
find * -type d— gives us a list of directories
fzf— provides us with an input to filter this list
cd— changes directory taking
fzfoutput as an argument
If you want to follow along, you can get
fzf from this installation guide.
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
. 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
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 * -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
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.
Here comes the last part of our command, let’s take the result of
fzf and pass it to
cd $(find * -type d | fzf)
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
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
# bash | zsh alias sd="cd ~ && cd \$(find * -type d | fzf)" # fish alias sd "cd ~ && cd (find * -type d | fzf)"
sd alias would stand for search directories and it’s similar to the good old
You could set this alias permanently by adding the line above to your shell configuration file i.e.
config.fish 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
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
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
I’m currently using
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
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.