Relocation: Basics
Note: there is a public repository containing the source code and formal documentation for the program that this post is about.
There seems to be an endless supply of solutions to the problem of moving around the filesystem quickly and efficiently. So what's one more?
I knew that rather than something that made it easier to switch to the most recently or most frequently visited directories I wanted my "relocation" command(s) to be deterministic, so that execution of the same command line would always switch to the same directory (assuming no changes to the underlying directory structure, and assuming the same initial working directory when switching to a directory with a relative pathname). That would make it easier to use the relocation commands in non-interactive situations like executing command lines retrieved from the command history and when "stacking" commands: that is, when typing a command or sequence of commands into the terminal while waiting for an earlier long-running command to complete.
Near the top of the file named relocate-functions.sh
in the repository are
instructions for setting up the commands that we'll be discussing, so we
don't cover that here. We also use the short names/aliases for relocation
commands, which get defined only if you use the "easy" installation method.
If you choose to define your own aliases instead¹ then it's recommended that
at least the one that's equivalent to the r
alias be given a fairly short
name, since the more you have to type the less convenient switching
directories will be.
Creating Relocation Aliases
My relocation commands centre around the idea of relocation aliases (not to
be confused with shell aliases), which are just short alphanumeric names for
(usually absolute, but possibly relative) directory pathnames. These aliases
are defined in the file ~/.relocations
, which has a very simple format:
- each non-blank line defines a relocation alias, and
- each such definition consists of the alias followed by the pathname of the directory it aliases, with a single space separating them.
Note: copying or appending the .relocations.example
file in the
repository to ~/.relocations
will give you some relocation aliases that
may prove useful later.
While the file's format is simple enough that one could just edit the file
directly to add a relocation alias, its safer and easier to use the rs
command. (In fact there's no command for deleting a relocation alias since
deleting the corresponding line/definition from the ~/.relocations
file is
easy enough to do while still making it hard to unintentionally remove an
alias.) The basic syntax of the rs
command is simply
rs alias dir
where 'alias' is the alias being defined and 'dir' is the pathname of the directory for which 'alias' is to be an alias. For example, the command
rs ed ~/.emacs.d
will define 'ed' to be the relocation alias for the directory ~/.emacs.d
(where the '~
' part will be replaced with the user's home directory before
the alias is added to the ~/.relocations
file). By default you can't
replace an existing alias, but the '-f
' option can be used to force its
replacement. So if you had earlier defined the 'b
' relocation alias with a
command like this:
rs b ~/backup
then running a command like this
rs -f b ~/bin
would make 'b
' an alias for your ~/bin
directory instead.
The rs
command can be used to define aliases for directories with absolute
or relative pathnames, depending on whether the directory passed to it is
relative or absolute. The one exception to this occurs when '.
' is
specified as the directory, in which case the alias will be an alias for the
absolute pathname of the current working directory. It's a key component of
how I define most of my relocation aliases:
- first I make the directory that I want to alias the current working
directory (using
cd
orr
), then - I run a command like
rs somealias .
to make a relocation alias for it.
In general the more frequently you plan on switching to a directory the shorter its alias should be, though an alias that you can't remember isn't very useful either.
Relocating
The r
command is used to switch — or relocate — to another directory. It
uses the built in cd
command internally to actually change the current
working directory, so it interoperates well with cd
and you can use
whichever of the two commands is most convenient in any given situation.
When run without any arguments the r
command relocates to the directory
that was the current directory before the last r
or cd
command was
executed, just as if you'd run the cd -
command (but faster to type). This
default is intentionally different from cd
's default so that you can run
cd
to quickly switch to your home directory and r
to quickly switch to
the previous directory.
When the r
command is executed with arguments then the first one must be a
relocation alias. If that's the only argument then — as you might expect — it
changes the current directory to be the one corresponding to that alias. Note
that if you're using the bash shell then you can use tab completion to
complete the relocation alias once you've typed the start of it.
But if you give the r
command two or more arguments then
- the second argument is used to select a subdirectory of the directory that the first argument aliases,
- the third argument (if there is one) is used to select a subdirectory of the one selected by the second argument,
- and so on while there are still arguments
and the subdirectory selected by the last argument is the one that will become the current directory. By default the second and subsequent arguments must match the start of the names of subdirectories, so for example the command
r ed themes
(where 'ed' is the alias for the ~/.emacs.d
directory that was defined
above) would make ~/.emacs.d/themes
the current working directory, but so
would r ed th
if there's no other subdirectory whose name starts with 'th',
as would r ed t
if no other subdirectory's name starts with 't'. Actually,
r ed th
or r ed t
might work even if there are other subdirectories with
matching names: when there are multiple matches then the one that comes first
lexicographically is used, while the other matches are reported on standard
error. For example, executing
r ed s
could result in output like
Also: /home/jgm/.emacs.d s -> site-packages, snippets /home/jgm/.emacs.d/saved
(where the first line gets written to standard error and the second — which is the pathname of the directory that was changed to — gets written to standard output).
Note that if one or more of the arguments after the first one doesn't match
an existing directory then the current directory won't be changed. For
example, if there's no subdirectory of ~/.emacs.d
that starts with a 'z'
then executing the command
r ed z
won't change the current directory. In particular it will not change the
current directory to ~/.emacs.d
.
There are also two built-in relocation aliases: '.' always aliases the
current directory and '/' always aliases the root directory. So the command
r / u
would likely relocate you to the /usr
directory, and following it
with the command r . lo b
could relocate you to /usr/local/bin
.
While the second and subsequent arguments to r
match the beginnings of
directory names by default, each and every '.' that appears in such an
argument will match any sequence of zero or more characters. So
r ed .he
will match any subdirectory of ~/.emacs.d
whose name contains 'he', such as
~/.emacs.d/themes
, but also ~/.emacs.d/eshell
. Since a '.' doesn't have
to appear at the start of an argument, the command
r ed .he.s
will relocate you to the (lexicographically) first subdirectory of
~/.emacs.d
that contains 'he' followed (eventually) by an 's'. As a last
additional minor convenience, an argument that contains a '.' that doesn't
match a directory name will (effectively) have a '.' prepended to it and will
be tried again. So the command
r ed he.s
can actually relocate to ~/.emacs.d/themes
too (though r ed hem
can't
since the second argument doesn't contain a '.').
That should be enough to get you started using the relocation commands. A later post will cover some of their additional features, as well as some additional related commands.
Updates
- For a real-world example of when you might want to define your own alias
in place of our
r
alias, reddit user whetu points out that the aliasr
is preset in the Korn shell.
If you'd like to support this site then check out my web app InEveryNook.com and see if it's of interest to you, pass it along to anyone you think might be interested in it, or both. Thanks!