Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Cdpath: Easily Navigate Directories in the Terminal (writesoftwarewell.com)
55 points by kuba-orlik on Dec 7, 2023 | hide | past | favorite | 43 comments


My surprising finding was that its easier to just hardcode abbreviations to directories. The most unimpressive solution technically and yet also the most effective.

I have abbreviations for about 20 directories, which essentially combine "cd" and the directory path in one string, no spaces.

It works because I probably spend about 50-80% of my time in those directories, it's not too much to remember, and nothing can be faster than a one-word command abbreviation to that exact directory.


Same here. I use "c.<bookmark-name>" so that I can hit "c." and tab twice to see all my available bookmarks.

Then I created a little bash f function:

    bookmark <bookmark-name>
... that adds such an alias pointing to the current folder to my aliases file, and sources it.

The source, if anybody is interested:

  bookmark() {
   if [[ ! $1 ]]; then
    echo "Please provide a bookmark name (will be prepended with 'c.'):";
    read name;
   else
    name=$1;
   fi
   dir=$(pwd);
   echo "alias c.$name='c $dir'" >> ~/.bash_aliases_local
   source ~/.bash_aliases_local
  }
Very efficient!

The reason I use c. rather than cd. is partly because I use an alias "c" all the time instead of "cd", that does all of this:

- cd into the folder

- run ls -ltr to see my last modified files at the bottom near the prompt.

- create an empty like with echo

- run pwd to print out the current folder path.

This was after I ran statistics on my bash history file and realized I constantly running ls -ltr and sometimes pwd in new folders.


What was my surprising finding in this, is that I don't need to think much about how I name the bookmarks either.

I can just throw in new short-hand bookmarks for whatever I'm working at the moment.

If I happen to override any previous aliases, that doesn't matter much if I already forgot about that one anyways.

Another cool thing: You can check the end of your ~/.bash_aliases_local file to find out what are your most recent bookmarks, and in other words, what are the relevant folders you are using a lot right now.

One can of course also clean up this list of bookmark-aliases from time to time, but I often don't even care about that.


The source for my "c" bash function as well:

  c() {
    cd "$1";
    ls -ltra --color=always | tail -n 25;
    echo;
    pwd;
  }


Zsh has a better builtin solution.

    hash -d x=/path/to/x
Then you can cd to there with just

    ~x
And use it in commands like

    ls ~x/whatever/


On Windows, I used to use AutoHotkey hotstrings for that so that they'd be available in file dialogs and Explorer as well as the terminal. Example:

    ::$pmd::C:\my\directory
For those unfamiliar with AutoHotkey, it has a global keyboard hook that watches for hotstrings like this and expands them to the text after the second pair of colons.

"$" is a sigil I chose to use for all hotstrings since I didn't use a language that used it and it helped avoid collisions with text that wasn't meant to be a hotstring, "p" was my prefix for pathing hotstrings, and "md" was an abbreviation for the mnemonic I chose for this particular directory, "my directory."

Then I realized z saves you the work of all that by learning which directories you use regularly and letting you switch to them with partial matching on its arguments:

    z my dir
No more coming up with mnemonics and editing my hotstrings file when I started new projects; now z handles it.

For the GUI (file dialogs etc.), my profile script now includes a command that copies the current directory to the clipboard. I'm happy with that workflow since I pretty much always have a terminal open anyway.


Another option could be to have a tmux session open for each of your projects, although of course this wouldn’t survive reboots.


It does with the plugin tmux-resurrect. Not perfect, but good enough most of the time.


Me too, here's some of my most commonly used

    alias cdrs='cd ~/dev/rs`
    alias cdgo='cd ~/dev/go`
    alias cddev='cd ~/dev'
    alias cddl='cd ~/Downloads'


I have been using slightly customized bookmarks.zsh[1]. Bookmark a directoey by `bookmark .` and jump there later by double-tapping @ symbol. Works well with completions and stores bookmarks in .cache

[1]: https://github.com/VTimofeenko/monorepo-machine-config/blob/...


Same, i literally have an alias that is 'w', which takes me to my primary working dir. It's great.


I do the exact same thing with bash aliases.

cdd is for the desktop.


The article spends a little time talking about the drawbacks of using CDPATH because it will break scripts, but the better answer is simply not to export it. CDPATH is a shell variable, not an environment variable, and should be treated that way.

Simply use "CDPATH=here:there" without the export, get the same functionality and no additional breakage.

Plus, on zsh you can use the tied variable cdpath instead of CDPATH(see typeset -T¹). cdpath is an array that accepts all the regular array operations. For bonus points you can even declare it with -U to remove the need to consider duplicates in your config. Other common -- and useful -- tied variables include path/PATH and fpath/FPATH².

¹ https://zsh.sourceforge.io/Doc/Release/Shell-Builtin-Command...

² https://zsh.sourceforge.io/Doc/Release/Parameters.html#Param...


I’ve been using autojump for years to the point of forgetting it’s not out-of-the-box behavior for zsh.

https://github.com/wting/autojump


For even more power use z

https://github.com/rupa/z


I prefer zoxide, which is very similar: https://github.com/ajeetdsouza/zoxide


That repo has an ad in its readme. Never seen that before.


And it's right at the top. This is a sure way to get me to ignore your software :(


Huh, I didn’t even notice. Yeah, that’s a new one on me.


I preferred fasd or specifically the oh-my-zsh fasd plugin for what I felt was more natural disambiguation completion (tab after vs remembering zi up front or space tab) and additional shortcuts.

I use zoxide now slightly reluctantly since fasd isn't maintained.


what do you prefer about it?


It’s a few things that aren’t big but add up: it’s compiled, and given how often it’s execute, that can make a difference (and especially on a heavily loaded system); it still gets updates; it plays better with Fish shell from my recollection; it supports fzf.

Z is perfectly fine. If zoxide didn’t exist, I’d use z instead. As it stands today, I think zoxide is niftier.


If you are willing to install a lua interpreter, https://github.com/skywind3000/z.lua is quite nice and has more features, e.g. fzf integration and an interactive mode.


Just installed z. After activating it, it outputs the directory when you use cd. Can one make that stop?


Did you change the _Z_CMD? If so, you have to include 2>&1. The default is

    alias ${_Z_CMD:-z}='_z 2>&1'


Thanks, just a misunderstanding from my side. Works now. Nice tool, already getting used to it.


Looking for a tool/shell that combines navigation and history. E.g. it would tell which commands I previously used while at the current directory.


I've had a great time using McFly (https://github.com/cantino/mcfly) for going through my command history. It prioritizes showing commands that were previously run in your current directory!


Whether the shell searches . absent its presence in CDPATH is shell dependent. It may not try . unless explicitly set.


Yeah I hit this hard and if I remember correctly it was the '/bin/sh' under Mac that did not look for .

That was nasty troubleshooting as CDPATH had been working correctly for years for me under Linux.


Here is a little fish function I've used for years.

  function p
      set -l argc (count $argv)
      if test $argc -eq 0
          cd ~/projects
          return
      end
      set -l project $argv[1]
      cd ~/projects/$project
      test $argc -eq 1; and return
      set -l file (fzf -q (string join " " $argv[2..-1]))
      test -z $file; and return
      $EDITOR $file
  end
Jumps to my project roots, and even opens my editor with extra args. Completion, too.

  set -l commands (command ls -p ~/projects/ | grep "/" | tr '\n/' ' ')
  complete -c p -f \
      -n "not __fish_seen_subcommand_from $commands" \
      -a $commands
Maybe someone who uses Fish will find this useful


I have a little bash script/alias that when you call it searchesy source directory for .git folders and lists all the parent directories in an fzf selector, which then cds to your selection.

I don't go anywhere else in my filesystem often enough to want anything more than that.


> If you put too many directories with common names into CDPATH and export it, it might break your scripts.

It will also break your shell history.

I’m probably in the minority but I’m wary of tools like this (asdf’s .tool-versions and similar things like rbenv/pyenv, and especially direnv) that change behavior based on the state of your shell’s working directory.

I like being able to ^R to a shell command from a month ago and just run it without worrying whence I’m running it.

I do like that you can directly use shims from asdf/pyenv/etc.


Why not just use symlinks in your home dir? Like: cd ~/blog


Because I don't want to constantly update 6000 symlinks as I add and remove directories in other locations.


The other option was to put them into CDPATH instead... 6,000 of them?

(I guess you are using an alternative to CDPATH, but you haven't said.)


No, because you put the parent directory in CDPATH. If I have funstuff/blogs/pics, funstuff/blogs/foods, funstuff/blogs/cats, etc., I put funstuff/blogs in CDPATH and now cd cats just works. If I created a pile of symlinks, I would have to individually create one symlink each for ~/pics, ~/foods, ~/cats, etc. And also type cd ~/cats.


I see. Thank you, I missed that aspect.

Of course, adding a symlink “~/f” that points to “funstuff” would work around the limitation, at the expense of typing two more characters. Four more if you count the leading “~/”.


Just automate the process using tools that use https://en.wikipedia.org/wiki/Frecency like autojump and fasd. No need to put a cognitive load on maintaining something that change over time when it can be easily automated.


I've been using zshmarks or bashmarks for years now. I couldn't get by without it at this point.

https://github.com/huyng/bashmarks

https://github.com/jocelynmallon/zshmarks


Very cool! Very helpful if you want to use the CDPATH variable in your shell scripts.

For my money, I just use fzf's built in Alt+C keybindings, as I outlined here [1] some months ago. It's been a game changer.

[1]: https://andrew-quinn.me/fzf/


Also, `cd -` to go back to the previous directory. And for git branches `git checkout -`. Handy.


I use https://github.com/ajeetdsouza/zoxide, which is inspired by z and autojump.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: