Skip to content

Blog Zero

10 Feb 2022

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 or r), 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

  1. 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 alias r 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!

Tags: shell software