Skip to content

bulletmark/cdhist

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Linux Directory History

PyPi AUR

cdhist is a utility which provides a Linux shell cd history directory stack. A shell cd wrapper function calls cdhist to intercept your typed cd command and maintain an ordered stack of all directories you have previously visited which can be listed and quickly navigated to.

cdhist can also be used with the Command Line Fuzzy Finder fzf to fuzzy search and select on previously visited directories, and can be used to easily cd between git worktree directories. See the sections below about FZF Integration and Git Worktree Integration.

The latest version and documentation is available at http://github.com/bulletmark/cdhist.

Example Usage

Use the cd command to change directory as normal:

$ cd /tmp
$ cd /etc
$ cd /usr/share/doc
$ cd /boot/loader
$ cd ~/etc
$ cd

At any point you can use the cd -- command to list all your previously visited directories and be prompted for one to select and cd to:

$ cd --
  6 ...
  5 /tmp
  4 /etc
  3 /usr/share/doc
  2 /boot/loader
  1 ~/etc
  0 ~
Select index [or <enter> to quit]: 3
$ pwd
/usr/share/doc

That's it! The above is all you really need to know. Instead of having to type the directory name you merely enter it's index. The directories are displayed most recently visited last, without duplicates. Index 0 is the current directory, index 1 is the previous, index 2 is the second previous, up to a user configurable number (default 50). Other available commands and options are:

List the current stack and its indices (without prompting):

$ cd -l

Change immediately to directory corresponding to stack index 4:

$ cd -4

Search back through stack for directory containing "string" and cd there:

$ cd -/string

Note, you can also type string at the cd -- prompt to search.

Show help/usage:

$ cd -h

Installation

Arch users can install cdhist from the AUR and skip to the next section.

Python 3.8 or later is required. Note cdhist is on PyPI so just ensure that pipx is installed then type the following:

$ pipx install cdhist

To upgrade:

$ pipx upgrade cdhist

Setup

A user who wants to use the cdhist facility should add the following lines to their ~/.bashrc or ~/.zshrc file (after where your PATH is set up so that the command cdhist can be found). This creates the cd wrapper command in your interactive shell session as a tiny function. Note you can customize the command name if you want.

if type cdhist &>/dev/null; then
    . <(cdhist -i)
fi

Then log out and back in again.

FZF Integration

The popular Command Line Fuzzy Finder fzf can easily be integrated with cdhist to provide fuzzy search navigation over your directory history. Set the following in your environment to have fzf search the directories recorded by cdhist:

export FZF_ALT_C_COMMAND="cat $HOME/.cd_history"

You also should make a small change to the way you source the fzf key-bindings and completions into your shell to ensure that the cd command is not aliased to builtin cd and instead invokes the cdhist command.

E.g. for bash, in your ~/.bashrc, instead of eval "$(fzf --bash)" as suggested by the fzf documentation, use:

eval "$(fzf --bash | sed 's/builtin cd/cd/g')"

E.g. for zsh, in your ~/.zshrc, instead of source <(fzf --zsh) as suggested by the fzf documentation, use:

source <(fzf --zsh | sed 's/builtin cd/cd/g')

After doing this (and reloading your shell session), you can use the fzf key binding <ALT+C> to have fzf list all your previous directories and fuzzy match on them for selection as you type. fzf can also provide fancy directory previews using tree, etc. Of course the cdhist native command cd -- and other cdhist commands described above are still available, in addition to the fzf key binding.

Pruning Non-Existent Directories

If you prefer that directories that do not exist are excluded from fzf and your cd history (i.e. exclude directories that have been deleted since they were last visited), then you can define the fzf command as:

export FZF_ALT_C_COMMAND="cdhist -p && cat $HOME/.cd_history"

An alternative is to always exclude non-existent directories from your cd history by setting the --prune-always as a default option.

Alternative Command Name

Some people may prefer not to alias their system cd command to this utility and just use an alternative unique command name. To do this, simply add your desired command name as an extra argument to the cdhist command in your shell initialization code. E.g, to use the command name xd rather than cd, use the following in your ~/.bashrc or ~/.zshrc file:

if type cdhist &>/dev/null; then
    . <(cdhist -i xd)
fi

Then log out/in, and then just type xd /tmp to change dir, xd -- to see and select directories, etc.

GIT Worktree Integration

cdhist can be used to easily cd between git worktree directories. You use the cd -g command to list all your worktrees and be prompted for one to select, and then you will be switched to the associated directory, and it will be added to your cd history.

# Current directory:
$ pwd
/home/mark/src/myprog

# List worktrees using standard git command:
$ git worktree list
/home/mark/src/myprog       f76b8e0 [main]
/home/mark/src/development  9796714 [development]
/home/mark/src/milestone1   bc921b8 [milestone1]
/home/mark/src/test         e6d965a [test]

# Alternately, use cdhist to list worktrees and choose one to navigate to:
$ cd -g
  3 ~/src/development 9796714 [development]
  2 ~/src/milestone1  bc921b8 [milestone1]
  1 ~/src/test        e6d965a [test]
  0 ~/src/myprog      f76b8e0 [main]
Select index [or <enter> to quit]: 2

$ pwd
/home/mark/src/milestone1

# Or, use cdhist to navigate to worktree dir for given branch name or
# commit:
$ cd -g main
$ pwd
/home/mark/src/myprog

Instead of having to type the full git repository directory name you merely are prompted with a list and enter it's index. Or just directly enter the branch name (or commit hash). The directories are displayed in the same order as the output of the git worktree list command, except that the git directory corresponding to the current working directory is shown first (index 0) consistent with how the current directory is shown at index 0 for normal cd history and thus conveniently showing you which git worktree you are currently in which git worktree list unfortunately does not show.

In you enter text instead of an index, you only need to enter as much of the branch name, or commit hash, as needed to be unique. Note that cd -g nicely presents paths based from your HOME directory with a tilde (~) unlike the longer full path displayed by git worktree list (although you can change that with the -u/--no-user option, likely set as a default option).

Relative Git Worktree Directories

The git worktree list command displays absolute directory paths, and cdhist does also by default, but many users prefer them displayed as relative paths. The Git worktree command does not provide this but you can enable it in cdhist by adding the -r/--relative option, e.g:

$ cd -gr
  3 ../development 9796714 [development]
  2 ../milestone1  bc921b8 [milestone1]
  1 ../test        e6d965a [test]
  0 .              f76b8e0 [main]
Select index [or <enter> to quit]:

Most likely you will want to set this as your default so do that by adding --relative as a default option.

Git Worktree Functionality Alone

Some users may want the git worktree functionality provided by cdhist but are not interested in the standard cd history functionality, or alternately, want to use a completely separate command for the git worktree functionality. To do this, simply add your desired command name and the git option as an extra argument to the cdhist command in your shell initialization code. E.g, to use the command name wt for git worktree functionality (only), add the following in your ~/.bashrc or ~/.zshrc file:

if type cdhist &>/dev/null; then
    . <(cdhist -i "wt -g")
fi

Then log out/in, and then just type wt to list the git worktrees and be prompted to select the directory etc. Of course, you can define this wt command in parallel to using cdhist for your cd command if you want.

Default Options

You can set default cdhist options by adding options in your shell initialization code, e.g:

if type cdhist &>/dev/null; then
    . <(cdhist -i "cd -arm 200")
fi

The above sets -a (--purge-always), -r (--git-relative), and -m (--size) 200 options as defaults for your cd command. Best to use the short option names to keep the imported shell function definition concise.

Note you can create one alias for your cd command, and another alias for your git worktree command (e.g. wt), and both can have different cdhist options.

The following options are sensible candidates to set as default options: -a/--purge-always, -r/--git-relative, -u/--no-user, -m/--size.

Note if you set -r/--git-relative or -u/--no-user options as default then options -R/--no-git-relative and -U/--user exist to allow you to temporarily override those defaults via the command line.

Command Line Usage

Type cdhist -h to view the usage summary:

usage: cdhist [-i] [-h] [-p] [-a] [-g] [-r] [-R] [-u] [-U] [-l] [-m SIZE]
                   [-n NUM_LINES] [-L] [-P] [-V]
                   [directory]

A Linux shell directory stack "cd history" function.

positional arguments:
  directory             directory (or branch for git worktree) to cd to, or
                        "--" to list history and prompt, or "-n" for n'th
                        entry in list or "-/<string>" to match for "string" in
                        dir

options:
  -i, --init            output shell initialization code. Optionally specify
                        alternative command name as argument, default="cd"
  -h, --help            show help/usage
  -p, --purge           just purge non-existent directories from history
  -a, --purge-always    always purge non-existent directories every write
  -g, --git             show git worktree directories instead
  -r, --git-relative    show relative git worktree paths instead of absolute
  -R, --no-git-relative
                        do not show relative git worktree paths (default)
  -u, --no-user         do not substitute "~" for home directory
  -U, --user            do substitute "~" for home directory (default)
  -l, --list            just list directory history
  -m SIZE, --size SIZE  maximum size of directory history (default=50)
  -n NUM_LINES, --num-lines NUM_LINES
                        limit output to specified number of lines
  -L, --follow-links    follow symbolic links (default=true)
  -P, --follow-physical
                        follow links to physical directory
  -V, --version         just output cdhist version

Limitations

Regular cd, e.g. as provided by the bash builtin, offers some esoteric command line options such as -e and -@, and shell options such as autocd, cdspell, cdable_vars. These rarely used options are not supported by cdhist.

License

Copyright (C) 2010 Mark Blakeney. This program is distributed under the terms of the GNU General Public License. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License at http://www.gnu.org/licenses/ for more details.