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 using
shell completion. Often 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 provide the
initial directory characters of that directory. E.g., if the intent is to
cd to /usr/local/bin, it’s easy to specify the letters
ulb.
Xd capitalizes on this capability. By providing the initial
directory characters of directories xd determines the expansion(s)
allowing you to do fast directory changes. So, after entering the command
xd ulb xd may directly perform the change-directory to
/usr/local/bin.
Often, however, multiple alternatives can match the specified
series of characters. E.g., when entering xd ulb xd may find
several alternatives, like
1: /usr/lib/base-config
2: /usr/lib/bonobo
3: /usr/lib/bonobo-activation
4: /usr/local/bin
If these are the alternatives, then this is exactly what xd shows you.
Then, by simply pressing the 4 key (no Enter key
required) xd performs the required /usr/local/bin (see also the
section DIRECT KEY ENTRY).
Xd’s behavior can be fine-tuned in various ways:
- o
- by default (as specified by the configuration file, see below) xd
looks for expansions starting 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 produces /tmp but not
/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). When merely specifying xd
. then xd changes the current directory to the user’s
home directory.
- o
- initial character 0: If the first character of the command is
0, then all expansions start at the current working directory. When
merely specifying xd 0 then xd returns leaving the current
directory unchanged. When additional characters are appended to 0 then
this command operates like the following, starting from the current
working directory;
- 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. When merely
specifying one of these characters xd changes the current directory
to the indicated parent, up to the root-directory (e.g., specifying xd
5 at /usr/bin changes the current directory to the
root-directory)
- 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 doesn’t produce 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 prepares for a
direct directory change to the solution’s directory.
If there are multiple solutions, then by default lists of at most
62 alternatives (10 for the numbers 0..9, 26 for the letters a..z and 26 for
the letters A..Z) are 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, except for the selected directory name
which should become the next working directory.
Xd may insert the cd command directly into the
command shell from where xd was called. See also section SHELL
SCRIPTS). In this mode of operation xd returns a single dot if no
selection is made, preventing an unintended change of directory.
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 its 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.
To pass the directory change command to the shell’s input
buffer xd calls the function ioctl(2). That function is still
available, although it’s also considered a somewhat deprecated
function. But even though it’s available, by default it may not work.
The program sysctl(8) shows the values of system variables, among
which dev.tty.legacy_tiocsti:
sysctl -a | grep tiocsti
dev.tty.legacy_tiocsti = 0
If, at your computer, sysctl shows
dev.tty.legacy_tiocsti = 0 then define a file
/etc/sysctl.d/tiocsti.conf containing the line
dev.tty.legacy_tiocsti=1
Then, after rebooting ioctl will work as described in its
man-page.
Alternatively, a shell script or alias can be defined to pass the
command to your shell. E.g., when using the tcsh shell program the
following alias can be defined:
alias xd ’cd `\xd --no-input \!*`’
Or, when using bash, define a function xd calling, e.g.,
/usr/bin/xd:
xd()
{
cd `/usr/bin/xd --no-input "$*"`
}
Xd also supports generalized directory search commands
(GDS). When GDS is requested separators are no longer required, and
xd finds all possible alternatives resulting from all possible
sequential combinations of the initial search command. GDS is activated
either by specifying the -g option or by entering
generalized-search in xd’s configuration file.
Alternatively, when the latter is specified then the --traditional
command line option suppresses 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*/ With 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 this case they force a directory change using 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 may return the following values to its caller, allowing
scripts calling xd to make decisions that depend on the actually
performed action by xd:
- o
- 0 is returned if xd issued a cd command;
- o
- 1 is returned if xd received a non-space character, not selecting a
directory to change to. When the input option has been specified
this character is inserted into the command shell’s input
buffer;
- o
- 2 is returned if xd received a space (or Enter) character,
indicating that xd should perform no further action;
- o
- 3 is returned if no directory was found matching the argument passed to
xd;
- o
- 4 is returned if the --help or --version option was
specified (see their descriptions in the OPTIONS section);
- o
- 5 is returned if an error was encountered (e.g., when a non-existing
configuration file is specified).
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.
Most options can also be specified in xd’s
configuration file, in which case the long option variants must be used,
omitting the initial two dashes (see the section CONFIGURATION FILE
below for specific details about the configuration file.
By default the options can also be specified in the configuration
file. If an option cannot be specifiied in the configuration file it is
explicitly stated at its description.
Options that are specified as command-line options take priority
over options specified in the configuration file.
- 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.
Conditions are
- o
- never (no additional search is performed),
- o
- if-empty (an additional search is performed if the initial search
did not yield any directory),
- o
- always (an additional search is always performed);
- o
- --all -a
If the configuration file (see below) contains ignore directives then
those directives are ignored when computing the alternatives from which
the user may select a directory to change to;
- o
- --block-size=nr (-b)
The possible directories matching xd’s argument are listed in
blocks of <nr> elements. the possible directories matching
xd’s argument are listed in blocks of <nr>
elements. The built-in minimum block size is 5. If there are fewer
alternatives then this built-in minimum then the actually available
alternatives are displayed;
- When alternatives are split up in blocks, a + is displayed after
listing the first block, a - is displayed after listing the last
block, and -+ is displayed after listing the intermediate blocks.
In these cases, pressing - redisplays the previous block, pressing +
displays the next block;
- Although these block-end prompts only show - and +, the characters , and
< (usually combined in one key) can be used instead of -, while . and
> (also usually combined in one key) can be used instead of +.
- 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.
- This option cannot be specified in the configuration file;
- o
- --directories inclusion
Directories may be also be reached via symbolic links. The (default)
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;
- o
- --generalized-search -g
When 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, whereafter
xd terminates.
- This option cannot be specified in the configuration file;
- 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;
- 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.
- The following history-... options are only interpreted if the
history option is also specified.
- 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]
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 are 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
Specify this option to use 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
- ignore path
This option cannot be specified as command-line option. Instead, 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 (interpreting the
final * 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
- --input
Xd itself issues the cd command for the selected directory to
the shell, and enters other (non alternative-selecting characters) into
the shell’s input.
- By specifying this option (or by entering input in the
configuration file) an extra shell alias or script is not necessary. In
this input mode xd directly inserts the requested cd
command into the shell’s input buffer. This mode has an additional
feature: if a key is pressed that is not assiciated with a possible
directory then the current directory is kept, and the character
corresponding to the pressed key is entered into the shell’s input
buffer. E.g., if xd ulb shows a list of five alternatives, but the
L key is pressed then xd ends and the shell’s input
buffer shows l. Merely pressing s + Enter will then show the
current directory content. To merely end xd in this mode the space
bar or Enter key can be pressed;
- To merely end xd press the Enter key or space-bar;
- o
- --no-input
The no-input option can only be specified as a command-line option
and suppresses the input option. The no-input option has no
effect if the input option is not specified.
- By suppressing the input mode xd writes the name of the
directory to change to to its standard output stream. This allows shell
functions to process the directory returned by xd. An example of
its use is the function pxd (pushd using xd) shown in
section SHELL SCRIPTS;
- o
- --start-at origin
Defines the default start location of directory searches. Origin home
(the default) 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;
- o
- --traditional
Xd does not use GDS but uses 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.
- This option cannot be specified in the configuration file;
- o
- --version (-v)
Xd’s version number is written to the standard error stream
whereafter xd terminates.
- This option cannot be specified in the configuration file.
The default configuration file is .xdrc in the
user’s home directory. It may be overruled by the program’s
--config-file command-line option.
Empty lines are ignored. Information at and beyond
#-characters is interpreted as comment and is also ignored.
Directives in xd configuration files follow the pattern
directive value
(for some directives there is no value term).
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 (except for the ignore directive, which are all interpreted).
All directives are interpreted case sensitively unless option
icase is specified. Non-empty lines not beginning with a recognized
directive are silently ignored.
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.
- o
- Example 1.
- To use xd in combination with the pushd shell command
xd itself should not perform directory changes. In such cases the
no-input option should be specified in the shell function combining
pushd and xd.
- To use xd with the bash(1)-shell, the following function can
be used (which could be added to, e.g., .bash_login):
pxd() # function to do `pushd` using `xd`
{
pushd "`/usr/bin/xd --no-input $*`"
}
To use xd with the tcsh(1)-shell, the following alias can be
defined in, e.g., the ~/.alias file:
alias pxd ’pushd `\xd --no-input \!*`’
- o
- Example 2.
- If the input option is specified (as command-line or configuration
file option) then this example can be ignored.
- 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
defined in, e.g., the ~/.alias file:
alias xd ’cd `\xd \!*`’
Having defined the xd alias or script xd ... commands results
in the automatic (or optional) change of the current working directory
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 as the
xd alias:
alias xd ’setenv XD "`\xd \!*`";cd "$XD"’
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
bash(1), ioctl(2), sysctl(8),
tcsh(1)
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).