What is this?
cdlog
is a small amount of GNU Bash code that provides a better
interactive experience for directory changes than
Bash's built-in directory stack mechanism (commands pushd
, popd
and dirs
, plus ~-
expansion).
How to use
Install the file cdlog.sh
somewhere, and source it from your
.bashrc
script.
When cdlog
is loaded, a number of commands become available:
-
cd
is an alias which calls the functioncdlog.chdir
. Every time you change directory, it pushes the previous directory into a history log which is stored in thecdlog_hist
array. The log maintains nine entries. The ninth entry is erased. The entries are copied into the variablesc1
throughc9
. The first four entries are also copied into the variablesx
,y
,z
andw
for shorter access. If the argument ofcd
is a number from 1 to 9, it changes to the specifiedcdlog
history element. -
cs
(cd swap) is an alias for a command which exchanges the current directory with a selectedcslog
entry selected by a numeric argument, which defaults to 1. The current directory overwrites that entry in the log, and then the shell changes to the directory which was previously in that entry. Ifcs
is given two or more arguments, it rotates among those. The directory is changed to thecdlog
item indicated by the first argument. That item is overwritten by the second item, the second by the third and so on. The last item receives the previously current directory. -
pd
(pop dir) is an alias for a command which changes to (by default) the most recent directory in the log, and removes that entry from the log. The second most recent directory becomes most recent and so on. If it is given an argument value in the range 1 to 9, it changes to the specified entry, and removes it, moving the others down to close the gap. Thuspd 1
is equivalent topd
.pd
takes a-f
option which means "force". This is useful when it's not possible to change to the indicated directory, in which case-f
causes it to be removed in spite of this. -
cdlog
function shows a listing of the four most recent entries in the log, or all nine if given the-l
argument. Thecl
command is an alias for forcdlog
with no arguments andcll
forcdlog -l
. -
The
mcd
andmcs
are menu-selection-based analogs ofcd
andcs
. They print the contents of the history (first nine entries), and you can pick which directory to change to or swap with. The terminal cursor is then retraced back to the top of the menu, and the screen is erased from that point to the bottom. -
The
cdr
command is used for switching to and managing previous sessions. Though ther
stands for "recovery", it may actually be used at any time and may be usefully used multiple times. Whencdlog
starts, it initially allocates a new session. Thecdr
recovery command presents you with a numbered menu of previous sessions. Entering an empty input line exits the menu. You can recover to one of the sessions by entering its number. The menu accepts additional notations for useful actions. Use ac
prefix on the numeric selection to clone the session into the current session. Deleting unwanted sessions is possible with ad
prefix; the specified entry is deleted and you remain in the recovery menu. There is ann
command which will make current again that new new session thatcdlog
had allocated on startup. That new session does not appear in the numbered list of recoverable sessions unless it has been already persisted by the execution of a directory-changing command. -
The
cdalias
command is used for defining or listing "cd aliases"; see below. -
The
cdunalias
command removes a cd alias. -
The
c
command provides an API intocdlog
's name resolution. It takes one argument. If it successfully resolves the argument to a path, that path it is printed, and the termination status is successful. Otherwise nothing is printed and the termination status is failed. If the argument is a digit in the range 1 to 9, then it resolves to the specified element in thecdlog
history, if it is nonblank. If the argument begins with@
, then it resolves as a search; see Searches below. Otherwise, it is tried as acdlog
alias; see Aliases below.
In addition, the cdlog.sh
script sets the Bash direxpand
option.
With the direxpand
option, Tab completion on a directory coming
from a variable name will expand that variable into the command line.
The directory changing commands do nothing if you attempt to change into the same directory you are already in. There is no effect on the history.
Aliases
cdlog
provides its own "cd alias" feature. If the argument to
cd
contains no slashes, then it is used as a key to look up an
alias, which replaces it. The replacement is not considered to
be an alias even if it looks like one. Aliases are defined using
the cdalias
command. It takes two arguments.
Implementation notes: aliases are stored in the cdlog_alias
array. The cdlog.chdir
function recognizes an alias only if
it is invoked as cdlog.chdir -p <alias>
, which is the way
cd
invokes it.
If the replacement (second argument) of cdalias
is a digit
from 1 to 9, then it refers to that entry in the cdlog
.
The path at that index will be retrieved and used as the alias value.
If the replacement begins with @
then it is a search. If
the search succeeds, then the result will be used as the alias
value.
When cdalias
is invoked with no arguments, it lists all the
currently defined aliases.
When cdalias
is invoked with one argument, and that argument
names an alias, it lists that alias. Otherwise it fails
with an error message.
The deprecated cdaliases
command also lists aliases; it
will disappear in a future version of cdlog
.
Searches
A search is an arguments which begins with @
. The rest
of the argument is interpreted as a pattern which is applied
against the history to find the most recent matching path.
In commands which accept a numeric argument denoting a reference
to the cdlog
history by position, the @
prefix may be omitted
from the search pattern. For instance cs foo
will
swap the current directory with the most recent history entry
whose path contains a match for foo
, and cs @foo
will do
exactly the same thing.
To include a leading @
as part of the search pattern, write @@
:
the first @
is recognized as the prefix, and removed; the
second @
remains as part of the pattern.
Persistence
Whenever the history changes, the current directory and the
contents of the history are written to the file ~/.cslog.N.dirs
,
one path per line, where N
is an internal session number.
(This location for the session file is only a default; see the
section Alternative Session Directory below which describes the
cdlog_sess_dir
variable.)
When cdlog
initializes, it allocates a session by finding a free
value N
in the range 1 to 10. If it cannot find one due to the
session store being full, it erases the one with the oldest time
stamp and chooses its index.
When one or more persisted session are present, cdlog
's initialization
mentions this, suggesting that the cdr
command may be used to recover
to one of the sessions. See also the Auto Recovery section below.
LRU Mode
When the configuration variable cdlog_lru
is set to the value y
, LRU mode
is enabled in the cdlog.chdir
function, affecting the cd
and mcd
commands. LRU mode modifies the history algorithm in the following way.
If the directory change successfully takes place to a directory which already exists in the history, then the most recent (topmost) occurrence of that directory is removed from the history before the previous directory is pushed into the history. Thus, in effect, a rotation is taking place: the existing entry in the history becomes the current directory, and is removed; the entries above it shift down to take its place, and the previous current directory becomes the top of the history.
LRU mode is disabled when the cdlog_lru
variable is empty,
which is its initial value.
LRU mode keeps duplicate directories out of the history and while promoting recently used directories toward the top.
Alternative Session Directory
By default, cdlog
keeps the session recovery files in your home
directory. They have numbered names like .cdlog.1.dirs
.
The variable cdlog_sess_dir
may be assigned a directory path
to specify an alternative directory. This path should omit the
trailing slash. If the variable is empty, it denotes the
root directory. If the directory doesn't exist, cdlog
will try
to create it. The main use for this configuration is to support
the situation when a home directory is shared among multiple
host machines with different environments. You can interpolate the
value of $HOSTNAME
into cdlog_sess_dir
to have sessions specific
to a host.
Auto Recovery
When the cdlog_autorecover
variable is set to y
, cdlog
will
automatically recover the session without the need for using the
cdr
command. This only happens when these two conditions hold:
-
Bash is either a login shell, or the
SHLVL
variable is1
. -
There is only one saved session.
This feature exists because it is extremely common to use cdr
upon logging in and to choose the only available session, by
selecting 1
. However, automatic recovery may navigate away from
the home directory, which may surprise the user who has not logged
into that host in a long time. Thus it is not default behavior.
When cdlog_autorecover
is empty, which is the initial value,
the feature is disabled.
Completion
cdlog
provides its own Tab completion for the cd
command, overriding
the built-in completion. It includes the cd aliases, while completing
on directories, taking into account CDPATH
.
How is this better?
-
It's not hard-coded C code inside the shell; it consists of a small amount of code whose behavior that can be customized by the end-user.
-
Uses simple variables, which are better supported for completion and require fewer keystrokes.
-
The
dirs
command for accessing the directory stack in Bash is too clumsy and won't be discussed here any more. -
Bash's shorthand notation for accessing the nth element, namely
~-n
, takes more keystrokes thancdlog
's aliases for the first four elements,$x
through$w
. -
Bash's shorthand notation requires an explicit slash to be typed in order for completion to work.
~-n
followed by tab is not sufficient. You must type a slash and then Tab. Whereas completing on the variable$x
just requires Tab. One tab will automatically add the slash and then additional tabs engage further completion. -
Bash's
direxpand
option does not work for~-n
notation. Completion works, but the notation remains unexpanded. -
Bash's
~-n
notation does not expand inside double quotes, whereas variables do. -
cdlog
has intuitive, simpler commands. The actions of pushing entries into the log, and rotating among them aren't conflated into a single command. The rotating commandcs
is usefully different frompushd [+/-]n
, taking only positive integer arguments with no sign, and rotating among specified places, rather than a contiguous block of top entries. -
The persistence feature recovers the directories from a previous session.
License
This is under distributed under a modified two-clause BSD license.
See the license block at the bottom of the cdlog.sh
file.