Bash Setup

The command line can be a powerful tool for smaller and bigger tasks. If you want to get a taste, have a look here. However, the amount of fun that you have while working with the command line crucially depends on how your command line is set up. Personally, I am a big fan of zsh and this repo to customize it. At some point, I might write about my own setup.

On clusters, however, there is not always a choice and the default shell on most Linux distributions is bash anyway. So, how do we make working with bash as much fun as possible?

Overview

There are two main files to change the way that the bash command line reacts: .inputrc and .bashrc. Both files live in your home directory ($HOME).

.inputrc changes the way that the GNU readline library reacts. This file alters way more than just the behavior of your bash. All programs that use the readline library will react differently.

The second option is the .bashrc. This is the user’s, aka your, configuration file for the bash. Here, you can define useful shorthands and functions to change the bash interacts with you.

An example .inputrc

Without further ado, let’s get started with the .inputrc.

TL;DR

Use this file as your .inputrc to have smoother experience while using the command line. Lines 2 and 3 enable searching with partial input by using the up-arrow. It is a game changer.

1set bell-style none
2"\e[A": history-search-backward
3"\e[B": history-search-forward
4
5"\C-f": forward-word
6"\C-b": backward-word
7
8set show-all-if-ambiguous on

Line-by-Line explanation

Let’s go through the file line by line.

  1. set bell-style none
    This line configures the bell (audible or visible alert) behavior. Here, we set the bell style to “none,” meaning that no bell will be produced when a terminal bell character is received. After all, who wants a beeping computer.

  2. "\e[A": history-search-backward and "\e[B": history-search-forward
    These two lines modify the search behavior of the readline library. The first line binds Up arrow (escape sequence \e[A) to the action history-search-backward. In practice, that means that you can start typing a command, let’s say python fo and by pressing the Up arrow, you get all commands from your bash history starting with those characters. In this case, it could be python foo.py --abc 3 --def 9. By pressing Up again, you will get the next match.
    In case you miss a match, we bind the Down arrow (\e[B) to history-search-forward, i.e. searching in the other direction. For me, this was a big change in terms of working on the command line. No more Ctrl+r all the time.

  3. "\C-f": forward-word and "\C-b": backward-word
    This line binds the key combination Ctrl + f to the action of moving the cursor forward by one word. In the same way, Ctrl + b will move the cursor back one word. If you are in emacs mode alt + b and alt + f will do the same for you.

  4. set show-all-if-ambiguous on
    This line sets the option enables the option show-all-if-ambiguous. When this option is enabled, readline will show all possible completions rather than ringing the bell if the tab key is pressed and there is more than one possible completion. As an example, imageine you have two files abcd.txt and abce.txt. By typing ls a<tab>, you get ls abc. This is the common prefix. Now, the option kicks in since there is no common prefix anymore. If you press <tab> again, you get

>ls abc
abcd.txt abce.txt
>ls abc

without the bell. I find that a very handy option.

An example .bashrc

There is not only the readline library, there is also the configuration of the bash directly

TL;DR

Here is an example .bashrc, for a user that might be calle foo. In case you are working on a managed machine, please do NOT just substitute your .bashrc. Adding it to the end is much safer.

The most important thing about a .bashrc: Define useful alias commands and shortcuts is key.

 1#
 2# MORE STUFF
 3#
 4
 5# Definition of environment variables
 6export PEPS_PROJ=/data1/foo/data/project/peps/
 7# Add an executable to the PATH variable
 8export PATH=$PATH:/home/foo/projects/peps/tools
 9
10# Define some alias commands
11
12## Related to SLRUM cluster operations
13alias squeuel='squeue --format="%.18i %.9P %.30j %.8u %.2t %.10M %.6D %R" -u foo'
14alias sinfot='sinfo -M all -N -o "%25P %16N %16T %16C %10z %.10e/%10m %10g %b"'
15
16## Related to git
17alias gd='git diff'
18alias gst='git status'
19alias gco='git checkout'
20alias gc='git commit'
21alias ga='git add'
22
23## Related to general navigation
24alias ll='ls -l'
25alias l='ls -l'
26alias ..='cd ..'
27alias ...='cd ../..'
28
29# Adapt the prompt to something that I like
30export PS1="\u@\h:\W> "

Section-by-Section explanation

Let’s have a look at the file section by section. Here, I will not explain every command, but rather the spirit of the sections. You will have to adapt the concrete commands anyway.

  1. Definition of environment variables
    Sometimes, it is handy to have some shortcuts for long directory names. Imagine you often have to change to a data directory or address files there. By defining an environment variable like $PEPS_PROJ, you can make changing directory smoother.

  2. Adding folders to $PATH
    If you want to call a program without typing its full path or even ./<name_of_program> in the same folder, the program must be in your $PATH. The bash reads your $PATH variable and checks in all folders whether the name that you typed is in there. If so, it is considered as a command and will be executed as such. If you write custom tools for your project, it makes sense to place the containing folder in your $PATH variable. In foo’s project, some of the tools can now be called from every directory of foo’s computer.
    The idea of the command in line 8 is to append a directory to the existing path. The first part of the command PATH=$PATH assigns the variable PATH to itself. Be careful with the spaces here. There are none. Bash is tricky with variable assignments. It only works without spaces.
    In Linux, the colon (:) character is used to separate directories from one another. By executing PATH=$PATH:<some_directory, some_directory is added to the back of the PATH. It is crucial that we are appending here, since Linux traverses the directory in PATH in order of appearance. Although you should never all a file ls, it gets much more annoying if that file ends up in your PATH before /usr/bin/ls.

  3. alias commands
    The most important tool, in my opinion, to make life on the command line more enjoyable are alias commands. An alias command gives a new name to an otherwise longer command. For moving up in the directory tree, I prefer to type .. instead of cd ... Thus, there is an alias ..="cd .." in my .bashrc. Note that there are again no spaces around the = sign. As you can see, there is a whole plethora of alias commands concerning git, SLURM and movement commands. Pick your favorites and start adding some yourself to your own .bashrc.

  4. Changing the prompt
    The prompt is the beginning of each line in the shell that is displayed before you type a command. I like to know where I am, both in terms of computer (hostname) and directory. Thus, here is an explanation of my favorite (bash) prompt "\u@\h:\W> ": \u: Represents the username of the current user. \h: Represents the hostname (the name of the computer) up to the first ‘.’. \W: Represents the current working directory (only the last part of the full path, not the entire path). If you like the full path, you can use \w. In words this looks like

<username>@<hostname>:<current_directory> >

If your user is called john working on a machine named mycomputer and his current working directory is Documents, the prompt will read

john@mycomputer:Documents >

I hope that this post makes working with the command line more fun for you. Let me know about your favorite setups in the comments.

Patrick Emonts
Patrick Emonts
Postdoctoral Researcher

My research interests include tensor networks, lattice gauge theories and quantum information.