It gives you this potentially constantly shifting set of shortcuts, essentially, and the problem is that means I have to constantly check I did get the result I wanted, and that I haven't accidentally gone to the wrong place. I found that more annoying to me than just using tab completions or history, which are much more predictable.
I can see how someone who has different workflows or environments might find it great though.
Also, re:
> the problem is that means I have to constantly check I did get the result I wanted, and that I haven't accidentally gone to the wrong place.
Is there a reason you don't add your current path to your prompt? I don't know how I'd work without that, never knowing which directory I'm in.
You can type `cd ~` and press CTRL+r to immediately fuzzy match commands you've run with `cd ~`. fzf naturally ranks paths to cd into on top. If you find that too noisy you can just hit CTRL+r with an empty prompt and then search for `^cd ~` to only find cd commands.
I've written about filtering related history with zsh here: https://nickjanetakis.com/blog/hooking-up-fzf-with-zsh-tab-c...
If you want to go into ultra lazy mode you can also type `cd ` and spam the up / down arrows to only show commands from your history where you cd'd into a directory. That use case is also covered in the above post. I normally don't use this for changing directories but it can be done.
And I do have my path in my prompt, I'm not talking about something that actually takes time, but more interrupts flow (for me, as I say, I get how for other people it'd work better).
My biggest annoyance at the moment (and this may be me missing something), is that I have two directories: "thing" and "thing-api". I'm doing work in "thing" much more often than in the "thing-api", but whenever I run "z thing", it takes me to "thing-api" first, and I have to "z thing" again to get to where I wanted to go. It ends up being more effort than if I'd just tab-completed or history searched a plain cd command.
However I agree z should ideally have some syntax like `thing$` to denote a full directory name instead.
> My biggest annoyance at the moment (and this may be me missing something), is that I have two directories: "thing" and "thing-api". I'm doing work in "thing" much more often than in the "thing-api", but whenever I run "z thing", it takes me to "thing-api" first, and I have to "z thing" again to get to where I wanted to go. It ends up being more effort than if I'd just tab-completed or history searched a plain cd command.
AFAIK the z command does take frequency into account (or was it most recent visit). However to avoid going into thing-api instead of thing I believe you just type thing/ i.e. At the slash and z will take you to thing (that obviously doesn't work with tab completion though).
I found that after some time I have gotten so used to z (which I aliases to cd) that I wouldn't want to live without it.
Run `zoxide query -ls thing` to see the scores, and `zoxide add thing -s AMOUNT` to increase the score.
source <(fzf --zsh) > /dev/null
and the ** shortcut followed by <TAB>, e.g. cd ~/** # <TAB>
along with cd - to change to the directory before cd -(PS: In Zsh `cd -<tab>` will show a pop up menu of all directories in the history stack.)
> fd -t d | wc -l
213842
takes 5 seconds.Population doing `cd ~/**<tab>` takes way way longer than 5 seconds though.
But regardless of the speed up one could add to cd + fzf in this case, I will still be using zoxide:
> zoxide query -l | wc -l
1294
and `zi` starts instantaneous if I need the dynamic filteringedit: layout
Other nice tools I use: Fish for shell (https://fishshell.com/), Starship for prompt (https://starship.rs/), bat "a cat with wings" for file preview (https://github.com/sharkdp/bat).
The folder-scoped and repo-scoped histories are great too.
It's really neat !
something like
alias zg=‘zoxide —basedir $(git rev-parse --show-toplevel)’
It was quite cool to see the power of such a tool, until the day I wanted to ncd into a directory with some code experiments I had built and just delete them all. Unfortunately the completion sent me into another directory, which I noticed after deleting all my parents tax documents.
DOS 3.3 didn't have an undelete command like later versions of DOS, so a colleague of my dad had to spend an evening trying to restore some of that data with some external tools. On the positive side, he also installed DOS 6.22 (we were really behind).
I've been a happy user of autojimp for many years, and just made the switch to Zoxide last week because it's maintained. I feel vindicated now :)
Here's the command I ran on macOS:
zoxide import --from=autojump ~/Library/autojump/autojump.txtIt being a native binary instead of Python-based might also help it execute more instantaneously. Most Python-based CLI helpers that I tried add a slight but noticeable delay to simple commands, whereas zoxide is so quick it's easy to forget you even invoked a helper in the first place.
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1110899
Migrated to zoxide instead, seems to work fine! Only need to get used to using z instead of j, muscle memory hard to adjust, might set an alias :)
I am certainly there are a whole host of security reasons not to, but it sure would be handy if a parent process could easily just read the final state of all environmental variables of a child process and possibly integrate them back into its own.
Shells could just have a syntax for accepting sub process environmental variables. I'd propose something easy like starting a line with = absorbing all set environmental variables.
We could build a custom cd tool, "custom-cd-bin" in this example and all that would need to do is change the PWD variable.
$ =custom-cd-bin ./foo
Maybe this will be something for my dream shell I'm never going to actually get around to building. It would take something gross like wrapping setenv thoughIt's just rarely used beyond dotfiles because... Well.. it inherits all variables etc
https://docs.vultr.com/how-to-use-the-source-command-in-bash
If you want to make the transition explicit at the end of the script, you can do what the sister comment did, essentially
"source <(bash the-script|grep -Pom "xx inherited variables\n(.*?)\n yy inherited variables")"
I'm talking about inheriting the environmental state of any subprocess. You can't source a binary.
fzf and zoxide are probably my two most game changing cli tools. They make the terminal feel so good.
I haven’t used it in a while though because I switched from git to jj.
0: https://github.com/rupa/z 1: https://github.com/CodesOfRishi/navita/
I use it with `eval "$(zoxide init bash --cmd cd)"` so I can continue to use CD due to muscle memory.
- I like that if there are multiple /foo directories known by Zoxide, say /foo/ and /abc/foo/, that you can do `cd abc foo` to go the path containing both.
- I am not a fan of having to do `cd foo**` for tab completion to folders outside CWD. I feel it slows me down as a tab complete fanatic.
- Also don't enjoy if I `cd foo/bar/batz` directly, then try `cd bar`, Zoxide has no reference. You would need to CD into each directory individually to build the database. I have seen scripts kicking around online to put a complete directory structure into Zoxide database by CD'ing to each subdirectory for you.
Not sure if I am officially sold, or I'll go back to aliases and simple tab completes forwards, and backwards (logic I use for tab complete backwards to exact directory name backwards from CWD instead of `cd ../../../etc` https://gist.github.com/GNOMES/6bf65926648e260d8023aebb9ede9...)This additionally is consistent and works without needing to “train” it first.
For me, this makes it so my expectations and muscle memory transfer cleanly between my workstation and other servers, devices, etc. I find the default tools are much more powerful than is often understood, and you can replicate most third party functionality fairly easily. That's not always the case mind you, and I happily use those tools.
You should use both in tandem!
Several years ago, I set up a keybinding that presents me all the directories stored in the zoxide[1] DB in fzf - in rank order. With just a few keystrokes, I get where I need to be, and I'm not presented with all possible directories - just ones I've visited in the past.
This solves the problem of "I want to go to a directory that's not the most ranked one for the string I typed, and zoxide keeps putting me in the other one".
Once you have this flow, there's no going back!
[1] Actually, I use autojump, but it should work with zoxide as well.
cd ~/foo; $COMMAND ; #optional cd ~ here
My history is full of this
As another example of why a simple CL utility for frecency alone is nice, you can basically replicate https://github.com/kantord/frecenfile with a shell 1-liner:
git log --pretty=format: --name-only | tac | sed '/^$/d' | lfreq -n9 -o.999
In a little timing test I did this morning, that was about 270X faster than the git log itself on the Linux kernel (61 seconds to git log, but only 227 ms to `lfreq` it).Besides all that, there's also the distributed-with-Zsh `cdr` (`man zshcontrib` or similar to read all about that).
On the rare occasion something is lost, it's a file, not a directory. Then I Spotlight (Mac super find) because it also searches content
qcd () {
local d
dirs=$(fd -t d -t l --ignore-file ~/.gitignore . $@)
d="$(echo ${dirs} | fzf +m --height=50%)" && cd "${d}"
}
alias hd="qcd ${HOME}"Could not imagine using regular cd for navigating file systems anymore.
With the exception of the fuzzy part, which can be added separately, Bash already has facilities for all of those functionalities.
The "remembering" part can be done via dirs/pushd/popd. The "using the basename only" part can be done via CDPATH. The "automated" remembering could be done via a super simple function wrapper over 'cd', adding things onto the the dirstack or the CDPATH respectively (and with a selection menu, possibly fuzzy, when clashes occur)
Putting it all together to achieve the same effect feels like a very simple 10-liner bash function at best.
Not dissing the author's work or idea, nor is there anything wrong with reinventing the wheel in another language for fun; but if you're going to claim that "z is a better cd" because it bundles all that other functionality for things that are unrelated to cd, and for which there are already pretty decent unix-philosophy-adhereing commands that you could be using effectively already, then if you fail to mention these things in your documentation, it feels a bit ignorant / disingenuous. I would have preferred examples with "without z you'd have to use CDPATH for this, and dirstack for that, and maybe this 5-line wrapper for the menu thing, etc".
Otherwise it feels a bit like saying "grep is a better ed" or something.
What you could argue with is whether there's a point to replacing the cd built-in in order to include fizzy finding (personally I don't see the point of this either). But the reason all the other cd features are included is in order to make that viable.
For example I have a big ~/src dir where I keep all my code checkouts. If I type 'z src' intending to go to ~/src/foo/bar/src, will it be clever enough to realise that I am referring to the second instance of the string 'src'?
I currently use a Fish port of the original 'z'. It does ignore the common prefix of _all_ matches (so if I only ever used it within my ~/src tree, the problem would disappear) but after that binary exclusion it works exclusively on frecency.
~/src/linux/linux
~/src/linux/stable
And I want to go to the first one? It doesn't have a unique sequence of keywords in it :/
Unless it recognises that if I type "z lin lin" I want the one where it appears twice?
I'm beginning to think my directory structure might just be toxic haha
abbr --add c cd
And then the "most used paths" are just present in the history filtered by the prefix I already typed.
chpwd() {
ls
}
It does what it says: after changing the cwd, list its contents. You can try other things, e.g. "[ -d .git ] && git status". function md
if test -z "$argv"
echo "md: Must supply an argument: The directory to create+cd into"
return 1
end
mkdir -p "$argv"
cd "$argv"
end mkdircd() { mkdir -p "$1" && cd "$1" }
mkdircd /tmp/new/directory/at/arbitrary/depthLooks like the tool doesn't handle that case very well.
In any case, aberrations such as the excessive use of emojis and exaggeration are becoming increasingly common, which is yet another reason for me to distance myself from GitHub. For me, a README that more closely follows the conventions and minimalism of a classic man page is a sign of quality, and it could perhaps even be rendered in plain text to achieve a high signal-to-noise ratio.
I mean, it's a hammer. It's fine. You can hit things. And pull out nails.
This thing runs on batteries and needs syncing and it's a hammer. It didn't need improving. It's an improvement on a rock, and it's all improved out.
Way to go.