Shaun Reed
bash
The following block contains a list of files related to bash, and their location / use.
1 | /bin/bash |
For more help, you can refer to the references and examples in /usr/share/doc/bash/
, or if you don’t have these files you can download them on Ubuntu with sudo apt install bash-doc
and see the /usr/share/doc/bash-doc/
directory. To help you explore these files, consider installing the terminal file browser ranger
with sudo apt install ranger
. If it is a .html
file, open it in a web browser to browse the file easily.
Creating Shells
From within man bash
, we can find the following explanation for the creation of an interactive bash shell -
When bash is invoked as an interactive login shell, or as a non-interactive shell with the –login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. The –noprofile option may be used when the shell is started to inhibit this behavior.
What this means is when a bash session is started that allows the user to interact with it by reading and writing, it will read from the /etc/profile
. After reading from this file, it will look for one of three files within the user’s home directory and read the first one that exists. This means that we can use the /etc/profile
file to set system-wide settings for all interactive terminal sessions. For me, this is useful to set the editor for all users to default to Vim with the exports to EDITOR
and VISUAL
below - if they want to override it, they can.
System Profile
First, the default /etc/profile/
can be seen in the code block below. I wrote some comments in the file to explain what the script is doing.
1 | # /etc/profile: system-wide .profile file for the Bourne shell (sh(1)) |
The above /etc/profile
configuration will set the default editor to vim, system-wide, regardless of which user is logged in. This includes the root user. Users can choose to override this in their own ~/.bashrc
, but users won’t be prompted to select their default editor since the system will now use Vim by default.
If you want to specify which user, or if you want to handle the root user independent from the rest of the system, take a closer look at the comments I’ve added in the above configuration file and modify as needed. You could specify a user ID here to source additional files, or you could just handle that sort of thing in that user’s ~/.bashrc
.
If you are trying to use the default text editor for any command ran with sudo
, be sure that you pass either the -E
or --preserve-env
argument. So, if we wanted to preserve our environment settings for the default text editor Vim when running vigr
or visudo
we would simply run sudo -E vigr
or sudo --preserve-env visudo
to ensure these settings are referred to when using sudo
User Profiles
After reading from /etc/profile/
, bash looks for one of three files - ~/.bash_profile
, ~/.bash_login
, and ~/.profile
, in that order. The first file that exists is sourced and bash stops looking. For evidence of this, notice the comments in the first few lines of the ~/.profile
file descibed by man bash
that points out the file’s order of execution. Just after, within the first condition of the file, it becomes obvious where ~/.bashrc
comes into play and things start to come to an end -
1 | # ~/.profile: executed by the command interpreter for login shells. |
All my ~/.profile
is doing above is sourcing the ~/.bashrc
file if it exists, and then adding some default directories to my user’s PATH
, if they exist. On different systems this can be handled differently. For example, below is an example of the same thing happening in a ~/.bash_profile
-
1 | if [ -f ~/.bashrc ]; then . ~/.bashrc; fi |
So we know now that when you want to edit settings for certain users who invoke their own interactive shells, the ~/.bashrc
file should be created or reconfigured. The rest of the page below will show some basic syntax for editing the ~/.bashrc
file, along with some examples.
Interactive Shells
An interactive shell is one that can read and write to the user’s terminal. This means that bash can take input from the user and provide some input back to them as a result. As described on the GNU Bash documentation, these shells often define the PS1
variable which we will cover later. This variable describes how the user’s bash prompt should appear within their session, and can often be fun or useful to customize. To start an interactive shell, you often use a login shell since you need to first authenticate with the system. On some more feature-rich systems though, you can start an interactive shell as a non-login shell, for example if you run a terminal application and you are already logged in - you are starting a new interactive shell without logging in, so you are in a non-login interactve shell.
Non-interactive Shells
An example of a non-interactive shell is one which does not take input and often does not provide output. An example of these could be running a script, when we invoke the script we start a new shell that runs that script - this shell is non-interactive. These shells do require login, since they are invoked by users who are already logged in, so they are also considered to be a non-login shell.
Skeleton Configurations
As stated in the first section, the /etc/skel/
directory contains files that are distributed to each new user created on our system. This is useful to know, since we can directly modify these files to provide different default configurations provided when new users are created. This can be a nice way to ensure that all users start with the same aliases, or are shown a similar prompt. We can even specify other defaults here, like providing a default .vimrc
to distribute to new users, or setting certain shell options.
Customizing Bashrc
Once logged in as your bash user, you can adjust your personal bash settings by modifying ~/.bashrc
, or /home/username/.bashrc
. If the file doesn’t exist, you can just create it and follow along with no additional setup required. If this file exists, it can at first be a lot to look at, but some of the more important lines to consider are seen below -
Bash prompt
1 | # This controls how your prompt looks within terminals logged in as your user |
Alias / export customizations
1 | # some more ls aliases |
Additional files to source
1 | # You may want to put all your additions into a separate file like |
Auto-completion
1 | # enable programmable completion features (you don't need to enable |
Environment Variables
PS1: Environment variable which contains the value of the default prompt. It changes the shell command prompt appearance.
1 | kapper@kubuntu-vbox $ export PS1='[\u@\h \W]\$' |
PS2: Environment variable which contains the value the prompt used for a command continuation interpretation. You see it when you write a long command in many lines. In most cases, this is set to >
, and is seen below after using the \
character to break the command into several lines -
1 | [kapper@kubuntu-vbox ~]$ export PS2='--> ' |
PS3: Environment variable which contains the value of the prompt for the select operator inside the shell script.
PS4: Environment variable which contains the value of the prompt used to show script lines during the execution of a bash script in debug mode. This could be used to show the line number at the current point of execution -
1 | # $0 is the current file being executed, $LINENO is the current line number |
PROMPT_COMMAND: Environment variable which contains command(s) to run before printing the prompt within the terminal.
1 | [kapper@kubuntu-vbox ~]$export PROMPT_COMMAND='echo -n "$(date): " && pwd' |
Bash Aliases
Create a list of aliases within your home directory inside a file named .bash_aliases
, and add any custom aliases or PATH
modifications there. The file may not exist, and if it doesn’t just create one and start listing aliases or settings. This way when you want to adjust something like your PATH
or aliases, you don’t have to dig through all the contents of .bashrc
. For example, some of the contents of my ~/.bash_aliases
is seen below. This file will automatically be sourced by bash when logging into our user, in addition to the contents of the ~/.bashrc
.
1 | # Alias / export customizations |
The gitkapp
alias above is a quick way of telling git who I am when logged in as a new user. You could imagine having more versions of this alias to switch to different git users quickly. Alternatively, you could use the git config --local ...
command within the alias to automate configuring a specific repository for a certain user in a single command without modifying your global git user. Aliases even automatically show up using auto completion -
1 | [user@host ~]$git |
Identifying Unicode Symbols for use in .bashrc
Character search engine
If you dont have access to a terminal, you can search up a symbol to get UTF8, see the below character and the corresponding UTF8 format as an example.
ഽ = 0xE0 0xB4 0xBD
To output this symbol in a bash terminal using this hex value, we can test with echo
-
1 | echo -e '\xe0\xb4\xbd' |
Note that these hexidecimal values are not case sensitive.
Hexdump unicode symbol
Most linux systems already have hexdump
installed, so we could also run echo ✓ | hexdump -C
to see the following output. Note that the -C
option displays character data in hexidecimal ascii format -
1 | [kapper@kubuntu-vbox ~]$echo ✓ | hexdump -C |
From this output, we can see that the UTF8 hexidecimal format of our symbol is e2 9c 93
. Using this information, we can test the character with the echo
statement below.
1 | echo -e '\xe2\x9c\x93' |
This will out our ✓
symbol, colored green. \001\033[1;32m\002
Begins the green color, and \001\033[0m\002
returns to
1 | echo -e '\001\033[1;32m\002\xe2\x9c\x93\001\033[0m\002' |
Unicode.vim
Worth mentioning that if you are using vim, an easy to use plugin that is useful for identifying characters is unicode.vim
. See my notes on Unicode vim plugin for more information, or check out the official Unicode vim repository.
In any case, when using special characters and symbols in an assignment to PS1
, you need to tell bash to interpret these values with a $
before opening your single-quotes, as in export PS1=$'\xe2\x9c\x93'
Bash Prompt
Your bash prompt is seen before you type a command -
1 | user@host:~/$ |
The prompt above, user@host:~/$
, is defined by the PS1 variable within your ~/.bashrc
where \u
is your username user
, and \h
is the hostname host
in the prompt above. The \w
in the prompt is what places our current directory ~/
before the final $
within the prompt -
1 | # Bash prompt settings |
By default within your .bashrc
there’s two settings to configure, the first block includes color, the second does not. When first learning about the prompt and all the available options like \u
, \h
, and \w
, it might be easier to look at the second prompt without the escape sequences for adding color. As we will see later, care must be taken to properly escape non-printing characters within your prompt, specifically color codes. That is the meaning of character sequences like \[\033[01;32m\]
or \001\033[01;32m\002
. Later we will cover the meaning of these symbols and how to properly organize them within your prompt.
You can change this prompt using the variety of settings below. Test your prompts with export PS1='<YOUR_PROMPT_HERE>'
and after you’ve got a good export working, paste it into the ~/.bashrc
to apply your changes each time you login. If you do not put the PS1
assignment within your ~/.bashrc
and log out of your terminal with an export applied, when you login it will be overwritten by the code above.
The ${debian_chroot:+($debian_chroot)}
portion of PS1
above only impacts our shell when we are using a chroot
, which is a way of chaging the root directory of the system into a smaller virtualized environment that exists within the system. So if we are using a chroot, the we will see the following prompt -
1 | (chroot-name)user@host:~/$ |
You can remove this ${debian_chroot:+($debian_chroot)}
portion or leave it, entirely up to you.
Prompt Options
When setting your bash prompt, we have the following options available to use. Options are useful for getting information from the current bash session dynamically. For example, \u
can be used to place the current username in the prompt, and \h
will print the hostname. So the prompt export PS1='\u@\h:
will make our prompt username@hostname:
1 | \a The ASCII bell character (you can also type \007) |
Background color codes
This section will cover using escape sequences to change the background color used within your bash prompt. This will have the effect of ‘highlighting’ the text in a certain color.
The following sequences can be used to set attributes that impact the background color of text print within a bash terminal. Notice that each color has a corresponding light color by changing the leading 4
to a 10
. For example, in the color sequence [42m
and [102m
for green and light green background colors, respectively -
Default color | \001\033[0;49m\002 | ||
Black | \001\033[0;40m\002 | White | \001\033[0;107m\002 |
Light Gray | \001\033[0;47m\002 | Dark Gray | \001\033[0;100m\002 |
Red | \001\033[0;41m\002 | Light Red | \001\033[0;101m\002 |
Green | \001\033[0;42m\002 | Light Green | \001\033[0;102m\002 |
Yellow | \001\033[0;43m\002 | Light Yellow | \001\033[0;103m\002 |
Blue | \001\033[0;44m\002 | Light Blue | \001\033[0;104m\002 |
Magenta | \001\033[0;45m\002 | Light Magenta | \001\033[0;105m\002 |
Cyan | \001\033[0;46m\002 | Light Cyan | \001\033[0;106m\002 |
Foreground color codes
This section will cover using escape sequences to change the font color used within your bash prompt
Using the appropriate bash syntax and the codes below, the \001\033[32m\002
escape code will colorize everything green after until output is reset with \001\033[0m\002
. Technically, the color code is only the [32m
portion, but it needs to be enclosed in \001\033
and \002
. \001\033
is the more portable option for \[\e
, and \002
is the more portable option for \]
.
So \001\003[32m\002
is both technically equivalent to and more portable than \[\e[32m\]
Also, the next section covers attributes, which make up the 0
in \[\e[0;32m\]
. So any attribute can be applied to any color by changing this leading value, or the 0;
can be removed entirely if normal text is used, as in \[\e[32m\]
.
The following sequences can be used to set attributes that impact the color of text in a bash terminal. Notice that each color has a corresponding light color by changing the leading 3
to a 9
. For example, in the color sequence [32m
and [92m
for green and light green, respectively -
Default color | \001\033[0;39m\002 | ||
Black | \001\033[0;30m\002 | White | \001\033[0;97m\002 |
Light Gray | \001\033[0;37m\002 | Dark Gray | \001\033[0;90m\002 |
Red | \001\033[0;31m\002 | Light Red | \001\033[0;91m\002 |
Green | \001\033[0;32m\002 | Light Green | \001\033[0;92m\002 |
Yellow | \001\033[0;33m\002 | Light Yellow | \001\033[0;93m\002 |
Blue | \001\033[0;34m\002 | Light Blue | \001\033[0;94m\002 |
Magenta | \001\033[0;35m\002 | Light Magenta | \001\033[0;95m\002 |
Cyan | \001\033[0;36m\002 | Light Cyan | \001\033[0;96m\002 |
Reset attributes
The following sequences can be used to reset attributes that impact the appearance of text in a bash terminal, returning them to normal after the attribute was previously set. Note that the reset is technically only [0m
but these also need to be wrapped in \001\033
and \002
-
Reset all attributes | \001\033[0m\002 |
Reset bold and bright | \001\033[21m\002 |
Reset dim | \001\033[22m\002 |
Reset underline | \001\033[24m\002 |
Reset blink | \001\033[25m\002 |
Reset reverse | \001\033[27m\002 |
Reset hidden | \001\033[28m\002 |
Set attributes
Any attribute can be applied to any color by changing the leading 0;
, or the attribute value can be removed entirely and the current attribute settings are used, as in \[\e[32m\]
.
The following sequences can be used to set attributes that impact the appearance of text in a bash terminal. Note that the set is technically only [1m
but these also need to be wrapped in \001\033
and \002
-
Set bold and bright | \001\033[1m\002 |
Set dim | \001\033[2m\002 |
Set underline | \001\033[4m\002 |
Set blink | \001\033[5m\002 |
Set reverse | \001\033[7m\002 |
Set hidden | \001\033[8m\002 |
Prompt Examples
Any of the below exports can be pasted directly into the terminal to be tested. Once the terminal is closed, these settings will be lost, so no worries about getting back to default. This is a good way to test what would happen if you changed the PS1 within your ~/.bashrc
, without actually doing so. If you mess up too bad, just close your terminal and open a new one. If you are logged in via ssh
, you’ll have to either source ~/.bashrc
or log out and back into the server.
Note that when using special characters and symbols, you need to tell bash to interpret these values with a $
before opening your single-quotes, as in export PS1=$'\xe2\x9c\x93'
Note that we do not need to escape hexidecimal characters that will be interpreted. See the below for examples
1 | # Ok |
When writing custom prompts, this can become a lot to take in all at once. The following prompt doesn’t even use color codes yet, and already it is quite the line -
1 | export PS1=$'\xe2\x94\x8c\xe2\x94\x80\xe2\x94\x80\u@\h\xe2\x94\x80[\W]\n\xe2\x94\x94\xe2\x94\x80\xe2\x95\xbc\$' |
What I like to do is split the prompt between several append statements to PS1
within my .bashrc
. An example of this prompt split across multiple lines shows it is much more readable and easier to adjust -
1 | # Printing ┌── |
Alternatively, for practice or playing around, we can create a new file called .practice_prompt
with the following contents. Then, we can just save the file and run source ~/.practice_prompt
from a different terminal to enable the custom prompt and see the changes -
1 | # Printing ┌── |
Splitting your PS1 assignment up not only makes it easier to read, but it suddenly becomes easy to comment out specific sections of the prompt when debugging issues with character spacing or adjusting the final appearance.
Simple Prompt
We can create a bare-minimum and simple export like the below, before adding any color
1 | # Example of what the prompt will look like |
Colorized Prompt
Adding color to the prompt makes things look a bit more complicated, but if we stick to the rules outlined in the sections above we shouldn’t have too much of an issue. Remember, if the prompt gets too long feel free to split it up between multiple appending statements within a file, then source that file. An example of this is shown in the earlier sections.
1 | # Example of what the prompt will look like |
Symbols in Prompt
Let’s take the colors out for now, and use some symbols to create a more interesting prompt. This prompt is based on the default prompt from the Parrot linux distribution. This prompt will use special symbols, so to begin we use echo ┌ └ ─ ╼ | hexdump -C
to get the below output.
1 | [kapper@kubuntu-vbox ~]$echo ┌ └ ─ ╼ | hexdump -C |
Notice we passed three symbols with spaces between them. If we run the command ascii
to see the ascii table, we can see that the value of the hexidecimal column for the space character is 20
. This is seen in the above output and helps to separate the hexidecimal values of our symbols so we can easily see where one begins and ends. We see that ┌
is e2 94 8c
followed by a space 20
, then └
which is e2 94 94
, and another space value of 20
. Next, the ─
symbol is e2 94 80
, followed by one more 20
and the final ╼
symbol’s hex value of e2 95 bc
. We will need to place the hexidecimal values of our special characters in the position we want the symbol to appear within our PS1
export.
Below, we use this information to correctly use symbols in our bash prompt. Note that while pasting the raw symbol will appear to work, it will cause bugs in your prompt. The method below requires more effort, but it will not cause character spacing issues within your prompt.
1 | # Example of what the prompt will look like |
Symbols and colors in Prompt
Here’s everthing together in one prompt.
1 | # Example of what the prompt will look like |