xd - eXtra fast Directory changer
The program xd is used to perform eXtra fast
Directory changes. Usually to change a directory the user is required
to enter a command like, e.g., cd /usr/local/bin, possibly with the
aid of shell completion. In many cases this is a tedious task: shell
completion shows all entries, including files, when we’re only
interested in directories and the full specification of our intented
directory may eventually require many keyboard actions.
Xd was designed a long time ago (in the early 90s) to
reduce the effort of changing directories. Often we’re well aware to
which directory we want to change, and it’s easy to produce the
initial directory characters of that directory. E.g., if the intent is to
cd to /usr/local/bin, it’s quite easy to produce the
letters ulb.
Xd capitalizes on this capability. By providing the initial
directory characters of directories xd determines the proper
expansion allowing you to change directories fast. So, entering the command
xd ulb results in the expansion /usr/local/bin.
Often life is not that easy. Often there are multiple expansions
from a given set of initial characters. E.g., when entering xd ulb
xd may find several alternatives. E.g.,
1: /usr/lib/base-config
2: /usr/lib/bonobo
3: /usr/lib/bonobo-activation
4: /usr/local/bin
If these are the alternatives, this is exactly what xd will show you.
Then, by simply pressing the 3 key (no Enter key
required) xd will produce the required /usr/local/bin.
Commands to xd can be specified so as to fine-tune
xd’s behavior:
- o
- By default (as specified by the configuration file, see below) expansions
may start at the user’s home directory or at the system’s
root directory.
- o
- Initial character /: If the first character of the command is
/ then all expansions are performed from the system’s root
directory. E.g., xd /t results in /tmp but not in
/home/user/tmp.
- o
- Initial character .: If the first character of the command is
. then by default all expansions are performed from the
user’s home directory. E.g., xd .t results in
/home/user/tmp but not in /tmp. The home directory
recognition character can be altered using the --homedir-char
option, see below (section OPTIONS).
- o
- Initial character 0: If the first character of the command is
0, then all expansions start at the current working directory. In
fact, this is a specialization of the following, more general form:
- o
- Initial character 1..9: If the first character of the command is a
digit between 1 and 9 then all expansions start at that
parent directory level of the current working directory (up to the
system’s root directory). E.g., if the current working directory is
/usr/share/doc then xd 2lb will offer the alternative
/usr/local/bin: two steps up, then look for directories starting
with l and therein directories starting with b.
- o
- Separators (space, and the forward slash (`/’)): sometimes
it is clear that there are many alternatives and the intention is to
reduce that number. By using separators subsequently nested directories
must start with the characters between the separators. E.g., xd u l
bi never produces the alternative /usr/lib/base-config anymore,
since base-config does not start with bi. In this case only
/usr/local/bin is produced. When used as initial character in a
pattern the forward slash always indicates the root-directory.
- o
- Search patterns may contain dots (like .s). In such cases the dot
represents hidden directories. However, xd usually also finds
patterns containing /./, as the current directory matches the dot.
Such patterns are considered spurious and are not reported.
If there’s only one solution, Xd writes that
directory to its standard output stream. If there are multiple solutions,
then a list of at most 62 alternatives (10 for the numbers 0..9, 26 for the
letters a..z and 26 for the letters A..Z) is written to the standard error
stream from which the user may select an alternative by simply pressing the
key associated with the selection of choice. If no selection is requested
any other key may be pressed (e.g., the space bar or the Enter key).
If there is no solutioon xd writes the text No Solutions to
the standard error stream.
When xd is given at least one argument, all its output is
sent to the standard error stream, but for the selected directory name which
is written to the standard output stream. If no selection is made or if the
selection process is aborted a single dot is written to the standard output
stream. Usually xd will be called by a shell alias, providing the
cd command with xd’s output (see below at the SHELL
SCRIPTS section) executing cd `xd $*`. The default dot produced
by xd prevents an unintended change of directory.
When xd is merely given an initial directory specification,
like a single dot (.) or digit (a digit in the set [0..9])
then xd returns the implied path. Specifying a parent before the
root-directory (E.g., entering `xd 5’ when the current working
directory is `/tmp’) results in writing the root directory
(`/’) to the standard output stream.
If xd is called without arguments then usage
information is written to the standard error stream.
Xd may be further configured using options and a
configuration file, discussed in the OPTIONS and CONFIGURATION
FILE sections below.
Starting with version 3.10.0 xd also supports generalized
directory search command processing (GDS). When GDS is requested separators
are no longer required, and xd will find all possible alternatives
resulting from all possible sequential combinations of the initial search
command. GDS is activated either by specifying the -g command line
flag or by entering generalized-search in xd’s
configuration file. Alternatively, when the latter is specified then the
--traditional command line option will suppress GDS.
When using GDS each initial substring of the command to xd
is considered as the initial characters of a directory. E.g., if the command
xd tmps is entered using GDS then directories matching the following
search patterns will be found;
- o
- /t*/m*/p*/s*/
- o
- /t*/m*/ps*/
- o
- /t*/mp*/s*/
- o
- /t*/mps*/
- o
- /tm*/p*/s*/
- o
- /tm*/ps*/
- o
- /tmp*/s*/
- o
- /tmps*/ Using the traditional processing mode only the first one of
these alternative patterns is considered.
Multiple command line arguments, the slash and the underscore can
still be used with GDS in which case they force a directory change in the
considered patterns. E.g., with the command xd tm/ps the following
patterns will be considered:
- o
- /t*/m*/p*/s*/
- o
- /t*/m*/ps*/
- o
- /tm*/p*/s*/
- o
- /tm*/ps*/ In this set all of the previous patterns showing the
...mp... combination were dropped, as a directory change is forced
between the m and p characters.
Xd returns 0 to the operating system unless an error occurs
(e.g., when a non-existing configuration file is specified), or
xd’s version or usage info is shown or requested.
If available, single letter options are listed between parentheses
following their associated long-option variants. Single letter options
require arguments if their associated long options require arguments as
well.
- o
- --add-root condition
If the search starts at the user’s home directory an additional
search starting at the system’s root directory may be performed as
well, depending on the value specified for the add-root option.
Alternatives are never (no additional search is performed);
if-empty (an additional search is performed if the initial search
did not yield any directory); or always (an additional search is
always performed). There is also a configuration file directive
add-root (see below).
- o
- --all -a
If the configuration file (see below) contains ignore directives then
these directives are ignored when computing the alternatives from which
the user may select a directory to change to.
- o
- --config-file=filename (-c)
The name of an xd configuration file. By default xd looks for
the file .xdrc in the user’s home directory. The existence
of the default file is optional.
- o
- --directories inclusion
Directories may be also be reached via symbolic links. The inclusion type
all adds these symbolic links to the list of alternatives. The
inclusion type unique prevents symbolic links from being added to
the list of alternatives. There is also a configuration file directive
directories (see below).
- o
- --homedir-char ch
By default an initial dot character (`.’) initiates a search
from the user’s home directory. There is a slight disadvantage to
using the dot, as it is also be the initial character of `hidden’
directories. Assuming that you have a directory ~/.ssh then the
command to xd to that directory would be xd ..s, the first dot
being the home directory indicator, after which .s is used to find
.ssh. The option --homedir-char can be used to specify
another character. Homedir characters cannot be digits or a slash
(`/’) as these are used to specify, respectively, parent
directories and the computer’s root directory. Characters like
``, @ % ^’’ or maybe `H’ (assuming that
it doesn’t interfere with an existing directory beginning with
H) could be used as homedir-characters, other than the default dot
character.
- Caveat: command shells by default interpret characters like ``~ $ \
’ " ` < > |’’ etc., which
therefore should probably not be specified as home directory
specifiers.
- There is also a configuration file directive homedir-char (see
below).
- o
- --generalized-search -g
When this option is specified xd uses GDS unless the directive
traditional is specified in the configuration file.
- o
- --help (-h)
Basic usage information is written to the standard error stream.
- o
- --history [filename]
A history of previously made choices is kept in the file filename. If
--history is specified, but the filename is left empty the history
file $HOME/.xd.his is used. This file should only be modified by
xd itself. If you can’t resist editing it then use the
following example showing the format of the lines in the history file.
1292596154 1 /home/frank/svn/xd/
The first field is the time (in seconds since the epoch) the entry was
written, the second field is the number of times the entry has been
selected and the third field is the associated path.
- o
- --history-lifetime spec
The lifetime of the entries in the history file. The specification consists
of a number followed by D, W, M or Y, representing, resp.
days, weeks, months, or years. A month is considered a period of 30 days,
a year a period of 365 days. If the specification is omitted a lifetime of
1M (one month) is used. Entries older than history-lifetime
are disregarded as history-items and are removed from the history
file.
- o
- --history-maxsize nr
The maximum number of entries the history file may contain. By default there
is no limit. When history-maxsize is specified and more than the
maximum number of history items are found in the history file then the
nr most popular choices are kept. Usually the cut-off point will be
somewhere within a popularity category. In that case the most recently
selected alternatives within that category are kept.
- o
- --history-position [top|bottom]
When this option is specified then previously found alternatives are
displayed either at the top of the list or at the bottom of the list. If
this option is omitted then the elements in the history will be intermixed
with new alternatives. The next option history-separate is only
used when this option is also specified. By merely specifying
history-position the history items are shown at the top of the
list.
- o
- --history-separate
When specified, a blank line is written between the items in the history and
new alternatives (not previously selected). This option is only
interpreted when the previous option is also specified.
- o
- --icase -i
This option is used to specify case-insensitive pattern matching. E.g.,
specifying xd /ub returns the directory /usr/bin, but not a
directory like /UnSpecified/Books, which is returned by xd
/UB. However, xd -i /ub (using any letter casing for the
specification) returns both directories. The option icase could of
course be specified in the configuration file, which which case
case-insensitive matching is used by default. In the latter case
specifying -i as a command line option reverts the matching
procedure to case-sensitive directory matching. In general, when an even
number of icase specifications is provided xd uses
case-sensitive directory matching, while an odd number of icase
specifications results in case-insensitive directory matching.
- o
- --start-at origin
Defines the default start location of directory searches. Origin home
results in all default searches to start at the user’s home
directory. Origin root results in searches to begin at the
disk’s root (/) directory. There is also a configuration
file directive start-at (see below).
- o
- --traditional
When this option is specified xd will not use GDS but will use its
traditional mode. It overrules a generalized-search directive
specified in the configuration file as well as the -g option.
- o
- --verbose (-V)
More extensive information about the actions taken by the xd program
is written to the standard error stream.
- o
- --version (-v)
Xd’s version number is written to the standard error stream.
The default configuration file is .xdrc in the
user’s home directory. It may be overruled by the program’s
--config-file option.
Empty lines are ignored. Information at and beyond
#-characters is interpreted as comment and is ignored as well.
All directives in xd configuration files follow the
pattern
directive value
but for some directives value is optional.
A line may at most contain one directive, but white space
(including comment at the end of the line) is OK. The same directive may be
specified multiple times, in which case the last directive will be
used (with the exception of the ignore directive, see below). All
directives are interpreted case sensitively. Non-empty lines not
beginning with a recognized directive are silently ignored.
The following directives can be used in the configuration file.
Default values are shown between parentheses.
- o
- add-root when (if-empty)
If the search starts at the user’s home directory an additional
search starting at the system’s root directory may be performed as
well, depending on the value specified for the add-root directive.
If when is specified as always then an additional search is
always performed.
If it is specified as if-empty then an additional search is performed
if the initial search (starting at the user’s home directory) did
not yield any directory.
If it is specified as never no additional search is performed.
- This directive is overruled by the ---add-root command line
option.
- o
- directories which (all)
Directories may be also be reached via symbolic links. The specification
all will add these symbolic links to the list of alternatives. The
specification unique will prevent the symbolic links from being
added to the list of alternatives.
- This directive is overruled by the ---directories command line
option.
- o
- homedir-char ch
By default an initial dot character (`.’) initiates a search
from the user’s home directory. There is a slight disadvantage to
using the dot, as it is also be the initial character of `hidden’
directories. Assuming that you have a directory ~/.ssh then the
command to xd to that directory would be xd ..s, the first dot
being the home directory indicator, after which .s is used to find
.ssh. The specification homedir-char ch can be used to
specify another home directory indicating character ch, as in:
homedir-char ,
Homedir characters cannot be digits or a slash (`/’) as these
are used to specify, respectively, parent directories and the
computer’s root directory. Characters like ``, @ %
^’’ or maybe `H’ (assuming that it
doesn’t interfere with an existing directory beginning with
H) could be used as homedir-characters, other than the default dot
character.
- Caveat: command shells by default interpret characters like ``~ $ \
’ " ` < > |’’ etc., which
therefore should probably not be specified as home directory
specifiers.
- This directive is overruled by the ---homedir-char command line
option.
- o
- generalized-search
When this directive is specified xd will use GDS by default.
- o
- history [filename]
A history of previously made choices is kept in the file filename. If
history is specified, but the filename is left empty the history
file $HOME/.xd.his is used. This file should only be modified by
xd itself. If you can’t resist editing it then use the
following example showing the format of the lines in the history file.
1292596154 1 /home/frank/svn/xd/
The first field is the time (in seconds since the epoch) the entry was
written, the second field is the number of times the entry has been
selected and the third field is the associated path.
- o
- history-lifetime spec
The lifetime of the entries in the history file. The specification consists
of a number followed by D, W, M or Y, representing, resp.
days, weeks, months, or years. A month is considered a period of 30 days,
a year a period of 365 days. If the specification is omitted a lifetime of
1M (one month) is used. Entries older than history-lifetime
are disregarded as history-items and are removed from the history
file.
- o
- history-maxsize nr
The maximum number of entries the history file may contain. By default there
is no limit. When history-maxsize is specified and more than the
maximum number of history items are found in the history file then the
nr latest choices are kept. Each previously made selection counts
as one. If a new alternative is selected it always becomes an element in
the history list.
- o
- history-position [top|bottom]
When specified alternatives found in the history will be displayed either at
the top of the list or at the bottom of the list. If this option is
omitted then the elements in the history will be intermixed with new
alternatives. The next directive history-separate is only used when
this directive is also specified. By merely specifying
history-position the history items are shown at the top of the
list.
- o
- history-separate
When specified, a blank line is written between the items in the history and
new alternatives (not previously selected). This directive is only
interpreted when the previous directive is also specified.
- o
- --icase -i
This specification is used to request case-insensitive pattern matching. If
this option is entered in the configuration file then specifying xd
/ub returns the directory /usr/bin as welll as a directory like
(assuming it exists) /UnSpecified/Books. When specified in the
configuration file, the command-line option -i reverts the matching
procedure back to case-sensitive directory matching. In general, when an
even number of icase specifications is provided xd uses
case-sensitive directory matching, while an odd number of icase
specifications results in case-insensitive directory matching.
- o
- ignore path
The configuration file may contain multiple ignore directives which
are --different from the way other directives are handled-- all
interpreted. Each ignore directive is followed by a path
specification as shown in a list of alternatives produced by xd or
an initial substring of such a path terminating in a * character.
When xd encounters a path matching any of the ignore
directives (with the * interpreted as `any further directory
name’ specification) it will not display that path in its list of
alternatives.
- This directive is overruled by the ---all command line option.
- o
- start-at value (home)
Defines the default start location of directory searches. Values are
home and root. When home is specified all searches
start at the user’s home directory. When root is specified
searches start at the disk’s root (/) directory. If the
directory is omitted or if another value is specified then the default is
used, which is home.
- This directive is overruled by the ---start-at command line
option.
- o
- traditional
This directive may be used to request the use of xd’s
traditional mode. It overrules the -g command line option and the
generalized-search directive.
Assuming xd is installed in /usr/bin scripts can be
defined around xd for various shell programs. This allows the shell
to change directories under control of xd.
To use xd with the bash(1)-shell, the following
function can be used (which could be added to, e.g.,
.bash_login):
xd() # function to do `cd` using `xd`
{
cd "`/usr/bin/xd $*`"
}
To use xd with the tcsh(1)-shell, the following
alias can be added to, e.g., the ~/.alias file:
alias xd ’cd `\xd \!*`’
If your system uses blanks in directory names, the above tcsh-alias cannot be
used as the blanks are interpreted as argument-separaters. In that case the
following alias can be defined:
alias xd ’setenv XD "`\xd \!*`";cd "$XD"’
Having defined the xd alias or script xd ...
commands results in the automatic (or optional) change of the current
working directory
xd ulb - all directories starting subsequently,
with u, l and b origin is default, or
specified in .xdrc as home or root
xd 0t - all directories starting with t below the cwd
xd 2t - all directories starting at the `grandparent’
(2 steps up) of the cwd
xd --start-at root t
- all directories at the root starting with t
xd .. - all directories starting with a dot in the cwd
xd . - the user’s home directory
xd 0 - the current working directory
xd 1 - the current directory’s parent directory
Assuming the following directories exist:
/usr/lib/bonobo
/usr/lib/bonobo-activation
/usr/local/bin
then the following two ignore specifications in
xd’s configuration file will result in ignoring the
bonobo directory alternatives:
First specification:
ignore /usr/lib/bonobo
ignore /usr/lib/bonobo-activation
Second specification:
ignore /usr/lib/bonobo*
- o
- $HOME/.xdrc: Default location of the configuration file
- o
- https://fbb-git.gitlab.io/xd/: Home directory
The program xd was initially (before 1994) written for the
MS-DOS platform. In 1994 it was redesigned to work under Unix (Linux, AIX)
and it was converted to C++. The original C++ code is still
available from tag start (https://gitlab.com/fbb-git/xd/tags,
find the start tag and download) and is funny to look at as it is a
remarkable illustration of C++ code written by C programmers
who had just learned about C++. Versions 2.x were used until
2008, and in late August 2008 I rewrote xd completely, reflecting my
then views about C++, eventually resulting in versions 3.x.y
and beyond. The 3.x.y and later versions extensively use the
facilities offered by the bobcat(7) library.
GDS was added to xd following a suggestion by Bram Neijt
(bram at neijt dot nl).
Frank B. Brokken (f.b.brokken@rug.nl).