Easiest guide to .bashrc
My journey with .bashrc
files has been hectic at best. Digesting the syntax and logic of how a bash
program is structured has always been an issue. I hope this will make people’s lives a bit easier and make bash a bit more straight forward. That being said, I love bash. There are countless cases that I’ve had a long sequence of terminal commands that need to be gotten just right. People say that bash is like a hammer and everything looks like a nail. In this case it is a nail.
To religious people regarding bash
convention. Yes, I break them, this is my personal convention. I consider bash
a personal journey where you express what you want your computer to do in a way that’s easiest for yourself and nobody else.
Contents
In this guide, we’ll explore a couple of concepts. We’ll not cover the prompt itself as these have probably one of the worst syntaxes that I’m aware of. I happily leave these to some online templates that there are plenty of.
What we’ll cover:
- Basic bash syntax
- Expressions (and environment variables)
- Strings
- Multi-file
.bashrc
- Automation
What we’ll not cover:
- Shell tools such as
du
,sed
,awk
etc. Those are outside the scope of this article - The prompt (
oli-TM1701 10:36 ~ $
in my case)
Syntax
Bash has a peculiar syntax which is not common in most of the modern programming languages. Do not mistake it though, in it’s oddities lies a lot of power and conciseness if written a clean way.
Functions
I’d like to start off with a basic function since they’re the building block of every program, and surprisingly, the most missing in most shell scripts I see. We simply print the arguments of the function.
print_args() {
echo $0
echo $1
echo $2
}

Note that $0
is the program executing the command, then arguments are listed as $1
, $2
and so on. We can then create some basic local variables like so.
print_args() {
local first=$1
echo $first
}
Note if you have a space between first
, =
and $1
the assignment won’t work. Now for the next confusing part…
Return values from functions
If you thought that you could get a return
value from a function by using the return
statement like in most languages I don’t blame you. It’s just that bash
does things a bit differently. The return
statement is only for return codes. Which, for those of you who remember C
or related languages is an integer
. That doesn’t mean it’s not useful though. Here’s an example using the very common &&
operator to concatenate bash operations.
passes() {
return 0
}fails () {
return 1
}

By now you should be wondering “How do we get return values then?”. The answer is the stdout
as we’ll see in the next section.
Evaluating expressions
Expressions are completely vital to any clean bash
script but, like everything else in bash
the syntax is not the best. This brings us to one of the core principles of bash. If you can see it in the console you can put it in a variable. Essentially making the basic printing of a variable with echo
equivalent to an expression instead of a procedure. That was a small brain-bender for me when learning bash
but alas, that’s how things are done. Here are a couple of examples:
Using the $(expression)
operator.
cool_string() {
echo "$1 is cool"
}very_cool_string() {
echo "$(cool_string Oli), very cool in fact."
}

Now we have a couple of tools to do something a bit more fancy. Let’s take a look at the eval
command. eval
simple runs whatever is passed it as you would have typed it into the terminal directly. Here’s a fun example where we create a function that creates environment variables for no reason:
var() {
eval "export $1=\"$2\""
}
If you don’t know the export
command then it’s a way to assign environment variables to your shell session.

Strings
So now we’re up to the point where attentive readers realize that everything about bash comes down to having strings, executing them and/or converting them to a different strings. Now it should start to become clear why there are so many tools to manipulate strings on Linux such as sed
, awk
, grep
etc. We can literally just get a feed of strings, manipulate them into a bash
command and execute them and it’s lightning fast!
Let’s do some string templating like we’ve been using above.
date_strings() {
local date_arg="next Fri"
echo 'date --date="$date_arg"'
echo "date --date='$date_arg'"
echo `date --date="$date_arg"`
echo $(date --date="$date_arg")
}

'
: Is the what you see is what you get (WYSIWYG) way to do strings.
"
: Is the string templating. Just like the f'template {variable}'
in python or `template ${variable}`
in javascript. In this case the curlies {}
are simply normal variables.
`
: Is the same as $(expression)
. Which might look confusing at first since it’s not really a string or string template but a function call / expression evaluation.
Conditionals
If you were hoping this one was intuitive then I’m sorry again. Conditionals are kinda funky especially under the hood. Let’s start by explaining a program called [
(yes, a program).
It takes in arguments and flags like [ arg1 -flag arg2 ]
with space between them. This is why we get this hilarious error when we type ["arg1"
into the terminal since it’s not a syntax error.

Now let’s use our prior knowledge to look at the conditionals. Since we know that [
is a program, and program has a return value (0 if it’s all good, otherwise an error-code, like 1). Let’s run the [
program with a couple of arguments.

It’s time to take a look at the if
statement in bash
. We’ll be using the -f
flag which means “does this file exist?” and use it to write an import
function for no reason. We’ll also be using the .
to load our file. To see what flags you can use check this page out, the -z
is particularly helpful. :)
import() {
local suffix='.bashrc'
local file_name="$1$suffix"
if [ -f $file_name ]
then
. $file_name
else
echo "ImportError: $file_name"
fi
}
Now we’ll try loading our ~/.bashrc
and a file called something.bashrc
which does not exist.

There is also another program for conditionals creatively called [[
which has very similar syntax but a different effect. In some cases it’s a simpler comparison.
Multi-file .bashrc
Well, with the tools above and the .
to specify a file to load as another .bashrc
you can pretty much do it yourself already. :)
Backing it up to .git
Just remember to do so, it’s important.
- Have your
~/.bashrc
as empty as possible. - Specify an environment variable to your folder of
.bashrc
files. - Load an
index.bashrc
or__init__.bashrc
if you will that loads the rest. - ???
- Profit.
Automation
So now you have most of the tools needed to create small functions for your bashrc
, give it a try and create some very basic functions. Using the syntax from above you can automate anything from a searching your bash
history with…
search_history() {
history | grep $1
}
to building and signing an android
apk. Remember though, it’s just like everything else: Nothing beats practice.
Thanks for reading.
Further reading
5 hours of trial and error can save whole minutes of reading the docs.
* Bash docs (accessible also in the terminal via man bash
)
These books have allowed me to leapfrog a couple of years of experience.
* Clean Code by Robert C. Martin
* Clean Architecture by Robert C. Martin
— — Edits to this article — —
1. Through the power of the internet the errors in my article were exposed and I updated the article with a bit more accurate information such as using local variables.
2. Added my favorite programming books to the article.