Intrepid command line directory traversal

[Tweet : ADN : nvALT]

I use Terminal (well, iTerm 2) for file management on my Mac more often than I use Finder. Typing out long path names is often more tedious than drilling through Finder folders, though1. I have enough tag-based Spotlight (mdfind) tools worked out in Bash that traversal in the shell has most of the same conveniences2, but still, some of those paths…

There are a lot of solutions available for efficient directory navigation in the shell. Here’s a quick rundown of my favorites.

Fuzzy history matching

There have been a few great solutions for jumping back through your history. From the Bash builtins pushd, popd, and dirs (see help [command]), we’ve progressed to tools like autojump and z. I’m partial to fasd, which is currently aliased to both j and z because MUSCLE MEMORY.

alias z="fasd_cd -d"

With these tools, every directory you cd to is remembered, and you can jump back to them with just fragments of their name. For example, if you were recently (or ever) in ~/Downloads/LaunchBar Actions/Forecast/, you can just type z forecast to get back there.

Bookmarking

I’ve been using a slightly customized version of the bashmarks (and zshmarks) system for a while for assigning quick aliases to commonly-used directories. Thanks to Jack at OneThingWell.org, I recently discovered Apparix, which is looking to be a more powerful solution. It provides additional utilities and (fuzzy) tab completion not only for the bookmark name, but for subdirectories off of the bookmark’s path.

Once again, I’ve aliased all of its features to the same commands I’ve been using for bashmarks. Creature of habit.

By the way, if you use bashmarks, here’s a handy trick (which you could also port to Apparix using the ~/.apparixrc file). I use the alias m for save, so bookmarking the current folder is just m [name]. To avoid bookmarking a folder twice with different names, I have an alias m? to check and see if it’s already bookmarked. It uses the l command (list bookmarks) and greps for the current working directory:

alias m?='l|grep "$(pwd)"'

One of my own solutions…

Here’s one of my own functions for jumping to subdirectories up to three levels from the working directory using fuzzy search. It incorporates fzf, which is brilliant and you should have it anyway.

# choose cd dir from menu (fzf)
# fuzzy search 3 levels deep
cdd() {
	local needle=$(echo "$*" | sed -E 's/ +/.*/g')
	cd "`find . -type d -maxdepth 3 | grep -Ei "${needle}[^/]*$" | fzf -s 20 -1 -0 -q "$1"`"
}

With this function you can drill into a directory tree quickly. If you’re in ~/Code/marked and you want to get to ~/Code/marked/vendor/multimarkdown/, you can just type cdd mmd and it will find the target and jump to it. If there are multiple matches, you’ll get the fzf screen where you can use arrow keys or typeahead filtering to pick the correct target.

Just add it to your ~/.bash_profile or any file sourced there. It’s not the fastest solution, but it doesn’t require bookmarking or that the target be a frequently used directory. In combination with up, it makes traversing project folders simple.

I also tend to combine Finder and Terminal navigation using my cdf and f functions. See more about those in this post.

LaunchBar can also be very handy as a shortcut for acting on a file or folder without digging into open commands:

# Select the current directory in launchbar, optionally a file
lb () {
    if [[ $# = 1 ]]; then
        [[ -e "$(pwd)/$1" ]] && open "x-launchbar:select?file=$(pwd)/$1" || open "x-launchbar:select?file=$1"
    else
        open "x-launchbar:select?file=$(pwd)"
    fi
}

Happy (cd) trails.

  1. to be fair, even in Finder I’m usually using ⌘⇧G and tab completing paths anyway…

  2. Did you know that mdfind -s [saved search name] will list the contents of a “Smart Folder” created in Finder?

Ryan Irelan has produced a series of shell trick videos based on BrettTerpstra.com posts. Readers can get 10% off using the coupon code TERPSTRA.