When using Linux to develop software, you often use a command line shell such as bash or zsh to access the full power of the operating system. Your project may be spread across multiple directories, causing you to switch directories often. Typing “cd ~/swdev/blog/retired-engineer.com/theme/blog” gets old pretty quickly. Below are several approaches to minimizing typing when doing CLI development.
Go to your home directory using cd
To change to your home directory quickly, simply type cd
with no parameters.
Example:
~/swdev/blog/retired-engineer/themes/blog% cd
~%
You can also type cd ~
. The symbol ~
is a shortcut for your home directory. When the shell encounters ~
, it replaces the ~
with your home directory path (example: /home/re).
~/swdev/blog/retired-engineer/themes/blog% cd ~
~%
The shell also recognizes the .
symbol as a shortcut to your current working directory. So, typing cd .
behaves as follows:
~/swdev/blog/retired-engineer/themes/blog% cd .
~/swdev/blog/retired-engineer/themes/blog%
Set cd search path using the CDPATH variable
Linux shells including bash and zsh support an environment variable named CDPATH
.
You are probably already familiar with the PATH
variable. But what is CDPATH
?
The PATH
variable tells the shell which directories to search to locate programs to run. For instance, when you type the command df
into the shell, the shell searches every directory in the PATH
for an executable file named df
. I often create a ~/bin
directory in my home directory, in which I store various executable binaries and shell scripts. By placing my current directory .
followed by ~/bin
at the beginning of my PATH as shown below, the shell first searches my current directory followed by my personal bin directory before searching other locations:
export PATH=.:~/bin:$PATH
If this command is placed in your .zshenv
file (for ZSH shell) or your .bashrc
file (for the bash shell), then PATH is set as shown above each time a new shell starts (such as when you log in).
The CDPATH
variable tells the shell cd
(change directory) command which directories to search. The cd
command searches CDPATH
when you type cd
followed by the name of a directory, and also when using tab completion (i.e. typing “cd” then hitting tab).
Assume you have several subdirectories in you home folder, such as:
/home/re
/home/re/bin
/home/re/documents
/home/re/downloads
/home/re/swdev
/home/re/swdev/downloads
Add /home/re
(or ~
) to your CDPATH
in .zshenv
or .bashrc
as follows:
export CDPATH=~:$CDPATH
Now, no matter what directory you are currently in, when you type cd downloads
, you will go to the /home/re/downloads
(that is, the ~/downloads
) folder. Unless, you are in the /home/re/swdev
directory, in which case you will go to the /home/re/swdev/downloads
directory. Why? Because cd
always searches your current working directory before searching CDPATH
(in other words, there is an implicit .
at the start of the CDPATH
).
If you type cd
then press tab (assuming you have tab completion enabled), you will be given bin
, documents
, downloads
and swdev
as completion options.
CDPATH
provides a handy way to minimize typing paths while moving around your system from the command line interface (CLI). I normally set CDPATH
to at minimum include my home directory as follows:
export CDPATH=~
Set shell alias
The shell alias
command can be used to assign a shortcut name to a longer command. Here are several example aliases from my .zshrc
:
alias df='df -h'
alias blog='cd ~/swdev/blog/retired-engineer.com'
alias post='cd ~/swdev/blog/retired-engineer.com/content/posts'
alias theme='cd ~/swdev/blog/retired-engineer.com/themes/blog'
The first line defines an alias so that when df
is typed in the shell, the shell executes df -h
. This technique works because when a command is entered in the shell, it first searches its list of aliases then searches the PATH
environment variable. This is a handy way to redefine Linux commands to enable options that you always use.
The following three lines define aliases that use the cd
command to switch to directory paths that I use to develop this blog
When I type blog
, theme
or post
into the CLI, the shell changes directories as shown below. This is a powerful way to save typing that I use often when developing this blog!
/var/log/some/long/path% blog
~/swdev/retired-engineer.com%
Source shell script containing cd
You may have tried creating an executable shell script in your ~/bin directory to switch directories similar to the script shown below. And it didn’t work. How could such a simple script not work?
Let’s create a file named “theme” that (tries to) switch directories:
#!/bin/bash
cd ~/swdev/blog/retired-engineer.com/themes/blog
Make the script executable (chmod +x theme
), and execute it by typing `./theme’. The script executes but does not change to the specified directory. Why?
In bash/zsh, when you execute an external command or shell script (such as df
) as opposed to a built-in shell command (such as alias
or cd
), Linux spawns a subtask from the shell to execute the command. As soon as the command/script completes, the spawned task completes as well.
This is a key concept, so let say it a different way: the shell executes built-in commands within the shell’s current context, but when executing an external command it creates a new context that is discarded when the external command exits.
So when you execute the shell script above (which is an external command), the shell spawns a new task, executes the cd command (which is a built-in command) which changes to the specified directory within the newly spawned task, then the external command completes causing the new task to exit returning you back to your original shell task – which is still in the original directory.
Linux shells have a built-in command source
which execute a script in the context of the current task, rather than spawning a new task. This is the proper way to use our theme
script to change directories:
~/some/directory/somewhere% source theme
~/swdev/blog/retired-engineer.com/themes/blog%
Tangent: How can you tell whether a Linux command is built into the shell or external?
Answer: Use the built-in shell command which
.
Here are some tests using the zsh shell:
~% which cd
cd: shell built-in command
~% which alias
alias: shell built-in command
~% which df
df: aliased to df -h
~% which du
/usr/bin/du
~% which source
source: shell built-in command
~% which which
which: shell built-in command
As seen above, the the du
command is external and is located in /usr/bin
, while df
is an alias for df -h
. The df
command is also external – trust me (or remove the alias, type which
, and prove to yourself that df
is also an external command).
Cd to variable
Yet another alternative for changing directories with less typing is to set a Linux shell variable then cd
to that variable. For instance:
~% xxx="/home/re/swdev/blog/retired-engineer.com/themes/blog"
~% cd $xxx
~/swdev/blog/retired-engineer.com/themes/blog%
Note that the variable must be set to the full absolute path – setting it to “~/swdev/blog/retired-engineer.com/themes/blog” results in an error message when executing cd $xxx
. Why? Because the shell doesn’t expand symbols such as ~
when they are found within an environment variable. Instead, the shell treats the contents of environment variables as literal strings that it does not process.
Tiling Window Manager
Common Linux Window Managers are GNOME, KDE, XFCE, etc. Instead of these, I use the i3 tiling window manager.
i3 allows window creation / resize / movement and even virtual screen management with very simple shortcut keys. For instance, pressing [Windows key][Screen Num] in i3 switches to virtual screen
A tiling window manager does not allow windows to overlap.
With a tiling window manager, you can open multiple CLI and non-CLI windows on a single virtual screen, arrange them as you like, and quickly switch between them via keyboard shortcuts.
Below is a typical layout I use when doing blog development. I view a local instance of the blog in a web browser in the left window. I edit CSS in the top right window (CSS files located in ~/blog/retired-engineer.com/theme/blog/static/css). In the two small windows in the lower right corner, I run the Hugo build command and the Cloudflare local development command. These both watch for changes and rebuild automatically. By keeping both open and visible, I can see if a change that I made causes a build error.
Bottom line is that with a tiling window manager, I work simultaneously in multiple directories spread across multiple virtual screens and quickly switch between them with keyboard shortcuts such as [Windows key][left], [Windows key][down] or [Windows key][3].
Summary
I have presented multiple approaches to minimize typing when changing directories. I am honestly a bit surprised at how many ways I found. Which of these approaches do I actually use?
- I set my
CDPATH
to my home directory as follows:export CDPATH=~
- I use aliases to point to blog directories as shown above
- I use the i3 Tiling Window Manager as my “daily driver”, and customize the screen layout when doing software development similar to the screenshot shown above.
CDPATH
works well when all the directories you want to switch to are at the same level, such as subdirectories within your home directory.
Alias works well when the directories you want to switch to are at different levels, such as the directory structure imposed by the Hugo static site generator software I use for this blog. Plus, you can type theme
to change to a directory named blog
!
Adopting a tiling window manager like i3 requires a steep learning curve. For me it was worth the effort, but I prefer using the keyboard rather than a mouse. I will discuss i3 in a future post.
Have fun changing directories!!