Behold z, the unsung jewel that rethinks shell navigation
aymericbeaumet.com
aymericbeaumet.com
I'm constantly amazed at what Windows dev people can get done without a programmable command line. I've seen several thousand line long cmd/bat files to do relatively simple things. They work, which is good. They are a lot of work to maintain though.
I find z absolutely wonderful to take away that first hurdle of remembering folders. I can't imagine how Windows devs who don't know Unix can get around easily. They seem to though. Much must be memorised and some tools help. Powershell is getting better, but I think lacks (at least for the moment) the amount of existing code/books/links that shell solutions have.
I sometimes hum my version of that old Sting favourite,
Oh, I'm an alien, I'm a legal alien
I'm a Linux dev in Windows 10....
I'd be interested to hear if there are better/equivalent searching tools easily available on Windows, but z works wonderfully for me.It's simple, for filesystem operations most Windows people don't use CLI. I use Total Commander for example, which has tabs and bookmarks to quickly navigate around the filesystem.
Windows has some nice tricks to connect the UI to the cmdline. For instance you can type "cmd" or "powershell" in the breadcrumbs-bar of an Explorer window, and it opens a terminal at that filesystem location (and the other way around, "start ." on the command line opens an Explorer window in the current directory.
Historically, pure command line workflows are somewhat rare on Windows though.
There may be more clashes, like picking up on filenames instead of directories.
Typing `z res` or whatever is also a bit faster than hitting ctrl-R then `res`.
It's not spatial because it's text-based but a similar problem occurs if it can surprise you about which location is going to be used for each input.
Best of both worlds, fish-like autocomplete combined with bash-compatibility :)
[0] https://github.com/clvv/fasd [1] https://github.com/sorin-ionescu/prezto
Agree that it's an invaluable piece of software!
I used to have a big list of aliases like:
alias pro='cd ~/Projects'
Seems trivial, but it was a huge time saver over time. After installing `z` and using it for a few days, I can now keep only the top 3/4 aliases and `z` does the rest.I've been tempted to try more fancy tools like zoxide, but I love the fact that `z` is just a shell script I can easily move around.
Directory history is the 3rd demo on the homepage: https://elv.sh/
As much as I love z, I'm also a fan of fzf, both are really complementary. I'm using this little piece of code (not from me, but cannot find the original source) to fallback to fuzzy search when z fails to find a result or when no args are given:
unalias z &> /dev/null
z() {
[ $# -gt 0 ] && _z "$*" && return
cd "$(_z -l 2>&1 | fzf --nth 2.. +s --tac --query "${*##-* }" | sed 's/^[0-9,.]* *//')" || exit 1
}
I also use this approach in a few other places in my workflow (git checkout, vim, etc). Expect a blog post covering this in the near future. cd ~/r/pr/e/de<tab>
Becomes cd ~/repos/projectlongname/environments/development
It also has built in push/pop, with minus always returning to the previous path, various numbers of dots, up to six I believe, navigating up the tree, and cd - <tab x2> showing interactive breadcrumbs of recent paths for easy as click-and-click navigation.With a compinit call the directory substring expansion will work. And, with auto_pushd enabled cd fiddles with the directory stack.
The ....... behaviour is interesting because it uses a global alias(alias -g) which is an awesome feature for text expansion anywhere in a line, unlike standard aliases which only expand where commands should be given. It means, for example, you can do `readlink -f ......` and it would perform `readlink ../../../../../..`. Aliases on zsh are very powerful indeed.
I'm writing this text in the hope it drives at least one person to burn an afternoon on the amazing(but huge) zsh documentation, because the entire thing is full of gems.
Seriously though, I think you were probably lucky to have experienced zsh that way. The out of the box experience is incredibly bare. Said as a fellow oh-my-zsh user going back the full twelve years, according to the history of oh-my-zsh's jnrowe theme ;)
I do believe there is a lot of useful knowledge to be gained from working back towards zsh first principles though, especially if -- like me -- you spend hours a day alongside the prompt.
I personally find that fzf is better because I can see where I'm going to end up before I accept the operation.
Even in the worst cases, at least with my i7 NUC and using fd instead of find, it's less than 500ms to load the entire list into fzf.
I personally find that fzf is better because I can
see where I'm going to end up before I accept the
operation.
I agree that's a must-have feature. Luckily z does it as well.Type `z foo` and hit tab.
If there's a single match, "foo" will be expanded in place to the proper path.
If there are multiple matches, you can choose from a list of paths.
So, no mystery navigation (unless you want it) -- you can always see where you're going.
(No external tools, so no forking of awk, sort, date, sed, mv, rm, and chown. Plus some stability improvements in terms of race conditions...)
$ export CDPATH=~/Workspace/src/github.com # in .bashrc
$ cd brigad/ops[This message brought to you by https://news.ycombinator.com/item?id=22978770]
z is Google (just give me what I want based on a short description of its name).
z is amazing.
bash source:
cz-index () { sudo find -L ~/work -type d -name '.git' | sed 's;/.git$;;' | sort > ~/git-dirs.txt }
cz () { cd "$(cat ~/git-dirs.txt | fzf --tiebreak=begin --exact -i -q $1)" }
I guess that's not quite as advanced as z or fasd though!
With zsh you can enable the auto_pushd option, which makes cd manipulate the directory stack itself. You could probably simply alias cd as pushd too under zsh too, but in bash that would break cd's argument handling.
For navigating between parallel directory structures (src/ and test/), I made an awful hack called c-, that sed subs src/ for test/ and vice versa on pwd. A fluke grade.