[Toolkit] Bash Basics

Brian Jones
10 min readDec 17, 2018

--

Learning to use a command line can be a daunting task for anyone, especially if you’re simultaneous trying to learn other concepts (e.g., vim, python, etc.). Hopefully I can shed some light on how to do some of the basics.

Table of Contents

Getting Started

The first thing you’ll need to do is open your terminal. How exactly you do this depends on your operating system.

  • Any Linux distribution: There’s going to be a terminal application bundled with the operating system (I would assume), open it.
  • macOS: There is an application installed called Terminal, open it.
  • Windows 10+: There are some steps to follow available at https://docs.microsoft.com/en-us/windows/wsl/install-win10. After you’re done, open the terminal.
  • Other: No idea… Hopefully you can figure it out?

The box that appears should look something like:

macOS Terminal

Now you have two options, the first is to read the below intro to bash. The second is to read Unix for the Beginning Mage which has a lot more information. And also magic! But it’s also a lot longer.

And finally, some warnings:

  1. I simplify some concepts a lot. This is often because a full explanation is too complicated but sometimes just because I’m lazy.
  2. If you’re following along with my examples (which I recommend), I’m assuming that you’re typing all the things that I have in my examples. If you skip any, it could have some weird unintended effects.
  3. Similar to 2, I’m assuming you’re typing exactly what I have. This means the exact same letters and the same spaces. Spelling and spacing are easy to get wrong but also matter a lot. If you get any weird error messages, spelling and/or spacing is probably why.

Terminology

Let’s start off with some terminology. Some of these terms aren’t that important to this intro, but they’re good to know.

A terminal is the program that we started up in the Getting Started section above. (Technically a terminal is a physical device, e.g., https://en.wikipedia.org/wiki/VT100. What we’re running is a terminal emulator.)

A shell (specifically a unix shell) is the language that you’ll be using inside the terminal. Shell and terminal are often (arguably incorrectly) used interchangeably.

sh (the Bourne SHell) was an early shell language created by Stephen Bourne in 1977. We aren’t using this one, but it’s good for context.

bash (the Bourne Again SHell) was written as a replacement to the Bourne shell (hence the name). It is probably the most common shell in use.

The prompt is the bit of text that appears on the left (in my above example it’s btjones:~ $ ). It will typically contain some useful information and then end with a $. It’ll be followed by the cursor which is an indicator of where you’ll be typing.

The Prompt

To make the following easier to follow, I’m going to strongly recommend changing your prompt to look like mine. This isn’t a permanent change (for cool stuff you can do with the prompt and how to make a permanent change, see my bashrc intro). This is just so that in my examples, it’s easy to see what’s the prompt and what’s not.

So, type in (and hit enter after):

btjones:~ $ export PS1='bash:\w \$ '
bash:~ $

Let’s go!

What’s in the Box?

This box we’re looking at (the terminal) is an old-timey way of moving around your computer (similar to Finder in macOS and File Explorer in Windows). We have folders, files, applications, etc. The main difference is that here we typically don’t use a mouse, we type commands. After typing the command, we tell bash to run the command by hitting enter.

First, let’s figure out in which folder we currently reside. This is done with pwd which is short for print working directory (directory is the old-timey name for a folder).

bash:~ $ pwd
/Users/btjones
bash:~ $

This says that I’m in the folder (directory) /Users/btjones.

Note: anytime below I type /Users/btjones, you should replace that with whatever you got instead. I’ll mention it again when it comes up.

Now let’s check what inside the folder (directory). We do this with ls which is short for list and it will list the contents of the folder (directory) we're in.

bash:~ $ ls
Applications Documents Library Music Public
Desktop Downloads Movies Pictures
bash:~ $

This says that I have 9 things and they’re named as you see. But is this all the stuff in the directory? We can ask to see all the contents of the directory with ls -a (the a stands for all). (Note the space between ls and -a.)

bash:~ $ ls -a
. .bash_profile Desktop Music
.. .bashrc Documents Pictures
.CFUserTextEncoding .ssh Downloads Public
.Trash Applications Library
.bash_history BashIntro Movies
bash:~ $

Huh, I have more stuff. As it turns out, files/directories that start with a period are hidden by default. We’re going to mostly ignore them for now, but just know that they’re there.

Next up, lets ask for some information about the files. This is done by asking for the long listing with ls -l.

bash:~ $ ls -l
total 0
drwxr-xr-x 2 btjones staff 64 23 Oct 20:45 Applications
drwxr-xr-x 2 btjones staff 64 23 Oct 20:45 Desktop
drwxr-xr-x 2 btjones staff 64 23 Oct 20:45 Documents
drwxr-xr-x 2 btjones staff 64 23 Oct 20:45 Downloads
drwxr-xr-x 2 btjones staff 64 23 Oct 20:45 Library
drwxr-xr-x 2 btjones staff 64 23 Oct 20:46 Movies
drwxr-xr-x 2 btjones staff 64 23 Oct 20:46 Music
drwxr-xr-x 2 btjones staff 64 23 Oct 20:46 Pictures
drwxr-xr-x 2 btjones staff 64 23 Oct 20:46 Public
bash:~ $

That’s a lot of information and I’m not going to talk about most of it. Some things to notice, each item now gets its own row. The d at the beginning of each row says that they're directories. The time (e.g., 23 Oct 20:45) is the last time those directories were changed. The last column has the names of the directories. The other bits are important, but not important to us right now.

We can also use both the a and the l together but I'll save that for later. Now, let's stop just looking around and change some stuff!

Making/Navigating Directories

First thing we should do is make a new directory to play around in. We do that with mkdir which is short for make directory.

Note: I’m not going to tell you how to delete this directory via bash when we’re done. This is because there are two main ways of doing so; one is quite tedious and the other is quite dangerous (I have accidentally deleted all my files before…). Instead I’m going to assume that you’ve deleted directories (folders) before via Finder/File Explorer/equivalent thing and can do so at the end if you would like to.

bash:~ $ mkdir BashIntro
bash:~ $

You might notice that unlike all the previous commands, this one didn’t display anything. This is going to be true of a lot of commands and generally means it worked (if it doesn’t work, there’s usually an error message). Let’s check with ls.

bash:~ $ ls
Applications Desktop Downloads Movies Pictures
BashIntro Documents Library Music Public
bash:~ $

It’s there! Now let’s go in! If this were something like Finder/File Explorer, we’d double click on it. That won’t quite work here (though you’re welcome to try). Instead we type another command (as you might have guessed). This one is cd, short for change directory.

bash:~ $ cd BashIntro
bash:~/BashIntro $ ls
bash:~/BashIntro $ pwd
/Users/btjones/BashIntro
bash:~/BashIntro $

If you’re using the prompt I suggested above, your prompt (like mine) will show you the directory. The ls shows us that this directory is empty. The pwd shows us that we are in fact in the BashIntro directory! But how do we go back?? As we just saw, when you use cd you also say the directory into which you should change. But how do I specify, the one "above" where I am?

Note: in bash any text after a # is ignored. These are called comments.

bash:~/BashIntro $ ls -a -l  # You can also do `ls -al`
total 0
drwxr-xr-x 2 btjones staff 64 24 Oct 21:48 .
drwxr-xr-x 18 btjones staff 576 24 Oct 21:49 ..
bash:~/BashIntro $

Huh. There are two directories (notice the d at the beginning of the lines) in this "empty" directory. A single period and two periods. Let's see what happens when we try to change to those.

bash:~/BashIntro $ cd .
bash:~/BashIntro $ pwd
/Users/btjones/BashIntro
bash:~/BashIntro $

We didn’t go anywhere… That’s because . is the current directory. So the command cd . means "change to the current directory" (which isn’t much of a change at all). Let's try ...

bash:~/BashIntro $ cd ..
bash:~ $ pwd
/Users/btjones
bash:~ $

We’ve done it! We escaped! As it so happens, .. means the directory "above" the one we're in. This is usually called the parent directory. Before moving on, I want to demonstrate a couple more ways to use cd. First, we need more directories.

bash:~ $ cd BashIntro
bash:~/BashIntro $ mkdir Dir
bash:~/BashIntro $ cd Dir
bash:~/BashIntro/Dir $ mkdir SubDir
bash:~/BashIntro/Dir $ cd SubDir
bash:~/BashIntro/Dir/SubDir $

First up is a shortcut. Typing cd with nothing after it takes us straight to your "home" directory (in my case /Users/btjones).

bash:~/BashIntro/Dir/SubDir $ cd
bash:~ $

Next is that we can cd multiple layers at a time.

bash:~ $ cd BashIntro/Dir/SubDir
bash:~/BashIntro/Dir/SubDir $

We’ve seen that ~ show up before the directories in the prompt ever since we started. Is that a directory?

bash:~/BashIntro/Dir/SubDir $ cd ~
bash:~ $

It is! The ~ means the home directory. (So, cd by itself and cd ~ effectively do the same thing.)

And lastly, we can type out the full name (the fancy term for which is the absolute path) of the location (the absolute path is the one we get with pwd and will start with a /) to which we wish to go (remember to replace /Users/btjones with your home directory).

bash:~ $ cd /Users/btjones/BashIntro/Dir/SubDir
bash:~/BashIntro/Dir/SubDir $

Dealing with Files

Now that we’re pros at dealing with directories, let’s play with files! First, let’s create a file. Typically this is done with a text editor (e.g., vim). But explaining how to use vim is a tutorial on its own and beyond the scope of this bash intro. So instead, I'm going to have you blindly copy and paste a command in order to make a file.

bash:~/BashIntro/Dir/SubDir $ cd ../..
bash:~/BashIntro $ echo "This is my text file." > my_cool_file.txt
bash:~/BashIntro $ ls
Dir my_cool_file.txt
bash:~/BashIntro $

We run into an interesting problem here, how do you tell files apart from directories? I put .txt at the end to hint that it's probably a text file, but this is purely optional. Names in bash have no special meaning. I could have named it DefinitelyADirectory and it still would have been a normal file (not a directory). So how can we tell them apart? There are a couple ways, one we saw earlier:

bash:~/BashIntro $ ls -l
total 0
drwxr-xr-x 3 btjones staff 96 24 Oct 22:43 Dir
-rw-r--r-- 1 btjones staff 22 24 Oct 22:51 my_cool_file.txt
bash:~/BashIntro $

When you use ls -l, directories start with a d. But this is a lot more information than I needed. Let's look at a new ls option!

bash:~/BashIntro $ ls -F
Dir/ my_cool_file.txt
bash:~/BashIntro $

The F option shows you what kind of file you have. Directories end with a slash (/) and "normal" files don't. There are other kinds of files as well, but none that we'll encounter here.

Now let’s see what’s in the file. We can display the contents of the file using cat.

bash:~/BashIntro $ cat my_cool_file.txt
This is my text file.
bash:~/BashIntro $

(If it seems like your prompt went away and your cursor is over on the left, you probably typed cat by itself without the file name. If so, control+c is a way to quit.)

Cool! We have a file! Now let’s make a copy! If this were Finder/File Explorer, we’d right click and pick copy. That won’t work here (but again you’re welcome to try). Instead we use cp, short for copy.

bash:~/BashIntro $ cp my_cool_file.txt file_copy.txt
bash:~/BashIntro $ ls -F
Dir/ file_copy.txt my_cool_file.txt
bash:~/BashIntro $ cat file_copy.txt
This is my text file.
bash:~/BashIntro $

The way cp works is cp <source_file> <destination_file> (if the destination file is a directory, you’ll make a copy inside the directory with the same name as the source file). So I said, take my_cool_file.txt (the source) and copy it to file_copy.txt (the destination). As we see from running ls and cat, it worked! When using this command, be very careful with your destination file. If I'd already had a file called file_copy.txt, it would have been deleted. Immediately. No questions. Just gone.

Well that’s rather frightening… Conveniently, we can actually get bash to warn us if we’re about to override a file. We do that with -i short for interactive. The exact wording of the below example may be different on your computer, but the intent will be the same. If prompted, you type y for yes and n for no.

bash:~/BashIntro $ cp -i my_cool_file.txt file_copy.txt
overwrite file_copy.txt? (y/n [n]) n
not overwritten
bash:~/BashIntro $

This is often helpful if we’re worries we might be copying over files we care about. We can be sure we aren’t accidentally deleting anything.

Speaking of deleting files, let’s do that! This is done with rm, short for remove. Similar to the above, there’s a -i option. This will ask you if you’re sure you want to delete the file.

bash:~/BashIntro $ rm -i file_copy.txt
remove file_copy.txt? y
bash:~/BashIntro $ ls
Dir my_cool_file.txt
bash:~/BashIntro $

Be VERY careful with this. Similar to above, it’s just gone immediately. There’s no prompting, it’s just gone. There’s also no trash bin. It’s gone for good. Whenever I type a remove command, I like to take my hands off the keyboard and read it over again closely before hitting enter.

Next up, let’s move files with mv.

bash:~/BashIntro $ mv my_cool_file.txt Dir
bash:~/BashIntro $ ls
Dir
bash:~/BashIntro $ cd Dir
bash:~/BashIntro/Dir $ ls
SubDir my_cool_file.txt
bash:~/BashIntro/Dir $

The mv command works similarly to cp. It's mv <source_file> <destination_file>. Also similar to the above, if the destination file is a directory, you’ll make a copy inside the directory with the same name as the source file. That’s actually what we’re doing here. We can also use mv to "move" a file to a new name.

bash:~/BashIntro/Dir $ mv my_cool_file.txt moved_file.txt
bash:~/BashIntro/Dir $ ls
SubDir moved_file.txt
bash:~/BashIntro/Dir $

Echo

The last command I want to mention is echo.

bash:~/BashIntro/Dir $ echo these are some words
these are some words
bash:~/BashIntro/Dir $

As you can see, echo just writes back what you typed (with some caveats). This has a lot of uses that are beyond the scope of this intro but it’s a simple command and good to know. (I also used it before to create a file so I felt I should mention it.)

--

--