sd -- a drop-in replacement for `cd'

Preliminary Remarks

We presume you are using either ksh or a mostly ksh compatible shell
(i.e. bash or zsh). sd can be used with tcsh, too, but there are
some minor restrictions and somewhat reduced performance.

After successful installation (see Initial Setup),
the file sd.ksh has to be sourced from within a running shell.
For routine use, the standard way to achieve this is to include the line

. sd.ksh

verbatim (including the leading ". ") in your resource file (e.g. .kshrc
or .bashrc). sd.ksh defines some shell functions whose names all start
with the string "sd". Relevant for interactive usage are only two of them,
namely

sd
sdirs (aliased to "dirs")

where sd is responsible for executing the desired cd command while
(s)dirs acts as interface to the other functions. Presuming there is no
shell function cd defined at the time sd.ksh is sourced, such a function
is automatically defined as

function cd {
sd "$*"
}

so that sd can be used transparently instead of cd. Altogether,
usually you only use the commands cd and dirs to interact with sd.

Usage

If a valid path to a directory is specified as argument to sd (or to the
cd function as defined above) it acts just as the builtin cd command
(including the cases where the argument is omitted or equal to -).

If the argument is not a valid path, it is interpreted as a regular expression
pattern and matched against a stack of directory names of previously visited
directories ordered by frequencies of visit. The first match found (if any)
is then used for the cd action. By definition this is most probably
correct (simply because that directory was the most frequently visited one
of all the directories matching the pattern) but is obviously not always what
you want. In this case the most direct strategy is to use a more specific
pattern.

Full regular expressions can be used but usually they are not necessary. If
they are used, take care to use adequate quoting. The most useful patterns
are either just substrings of the desired directory name (e.g. its basename
or a trailing part of the full path name). In order to enforce a match at the
end of the stack entries use something like

cd basename$

Instead of making the pattern directly match the directory you are
interested in, it's sometimes easier to issue

dirs pattern

where pattern is a usually non-unique match for the respective directory.
This command will display a list of all "hits" of the specified pattern
together with a rank index. This rank in turn can then be used to go to the
desired directory:

cd =rank_index

With zsh you have to escape the equality sign: cd \=rank_index.

Issuing dirs without an argument displays the complete content of the
currently available directory stack. Detailed usage information can be
obtained by issuing

dirs -m

Technicalities

The directory stack

The directory stack used by sd for lookup of directories is changing
dynamically and is generated/updated as follows:

At startup the stack is initialized from the trailing $sdlines (default:
512) lines/directory names in the logfile of previously visited directories
(default logfile: ~/.sd/dirv) by computing a frequency distribution of all
unique names.

The resulting list constitutes the directory stack which is queried top-down
in order of decreasing frequency when looking for an entry matching the
pattern specified for a cd action.

After each successful cd action, the name of the new working directory
is appended to the logfile and the stack is regenerated from the (now
slightly changed) $sdlines trailing entries. Naturally, if a certain
directory is visited sufficiently often, over time it will move up the
directory stack.

Obviously, the stack content and, especially, its order is sensitively
controlled by the chosen value of $sdlines. This value indirectly defines
the effective time window inspected by sd: by default the last 512 cd's
are tracked which, at moderately heavy use, does correspond to about 1-2
weeks of work.

Increasing the value of $sdlines extents the effective time window and thus
includes more distinct directory names in the stack. However, the stack
ordering does no longer change as rapidly. Rather, for large values of
$sdlines it approaches a nearly static sorting order. The bottom
line: there is to be made a choice between including a sufficiently large
number of directories in the stack and a stack that adjusts its sorting order
rapidly to a change of focus of the ongoing work (accompanied by frequent
visits to a different group of directories).

A further point to realize is the following: the directory stack is maintained
in a shell variable ($sdlist). The stack is thus internal to the
respective shell process. Especially, it does not change if another running
shell instance modifies the logfile (and it's own incarnation of the stack).
In order to "synchronize" the stack across different shells (usually in different
terminals) stack regeneration can be enforced via dirs -f (it might be easier
to just open another terminal, though).

The logfile

The logfile size is limited to $sdmax entries/lines (default: 8192). If
this limit is reached, the file is pruned to the 3/4*$sdmax = 6144
trailing/most recent entries. Thus, the accessible history fluctuates between
these two figures. This approach ensures that pruning occurs only vary rarely
(every few months, probably) and that the minimum time window is that of the
last 3/4*$sdmaxcd actions (many months, maybe over a year). dirs -i
reports the time of the last pruning.

Handling of non-matching patterns

Whether a

cd pattern

command fails, i.e. whether pattern does not match any entry in the current directory
stack, partly depends on the chosen value of $sdlines (which might be modified in
the corresponding resource file or increased interactively via "dirs -l num").

As an attempt to improve handling of such initially failing cd actions,
sd implements the following strategy
(also covering the case of "stale" entries, i.e.
entries pointing to a directory that has been deleted in the meantime):

If cd pattern fails,
first try to find another matching entry further down
on the stack.

If this fails too,
temporarily increase $sdlines to the total number
of entries in the logfile (usually several 1000).

Recreate the stack (which then contains all directories found in the
logfile) and try again to find a matching entry
(again, skipping over stale entries).

Reset $sdlines and recreate the stack.

In this way the chance of complete failure is distinctly reduced but it is of
course not guaranteed that the top-most "hit" on the extended stack is the
desired one. For this reason, a list of all hits on the extended stack
is displayed, too, in order to enable the user to refine the search pattern
if need be. To avoid this output define this shell variable:
sdsilent=1 .

This page was generated in about
0.006s by
Fossil 2.8 [3b17294dfe] 2019-01-07 01:32:14