Terminal basics

The terminal, the console, the command line. All three terms refer to the same thing.

Get access to a Linux system and open a terminal.

Warning ⚠️ : Don't panic!

Many find the terminal frightening. This is the cryptic thing you see hackers in films using! You might ask yourself, what am I doing here? I don't want to break my system or launch a terminator! 😯

Again, don't panic! What you see is just a prompt (usually on a dark background).

Now, how to interact with the terminal? You are probably not seeing a lot of buttons on your terminal. This is because you interact with it (mainly) through your keyboard. But what to type?

It is like a chat with your computer. But your computer is not into memes. It is a soldier waiting for your commands 💂‍♂️

Echo

Let's enter our first command! Type echo "Hello!" and press enter. This is the output:

$ echo "Hello!"
Hello!

Congratulation! You did just say hi to your computer and it did even reply! What a charm! 🤠

Well, to be more precise, you gave a command to your computer to say "Hello!" and it did so… I know, I did just brake the romance between you and your computer. I apologize. 😶

echo is a command that prints out what you give as an argument. It might not seem to be a useful command. Why would I want the computer to echo my words? The importance of echo will be clear mainly when writing scripts. More about this in later sections!

Let's try more commands. Type ls and press enter. What do you see?

The output is going to be the files and directories in your current path. ls stands for list.

What if you want to take a look at the content of a different directory at a different path?

To examine this, let's first create a new directory. Enter the command mkdir empty_house. Well, you don't see anything? Did the command do something at all? To check, run ls again. Now, you should see your new directory empty_house listed too! mkdir stands for make directory. empty_house is just a name for our new directory. You could have used mkdir Images for example to create a directory called Images.

Is empty_house really empty? Let's check.

Enter the command cd empty_house. Again, you don't see an output. But maybe you did notice that a part of your prompt changed from ~ to empty_house. This indicates that you are in your new directory. cd stands for change directory.

Now, enter the command ls. You should not be seeing anything because the directory is indeed empty, until now.

Create, rename, move

An empty house is a sad house. Let's give the house directory some friends to live within it. Enter the command touch friend1.txt. Now, enter ls again:

$ ls
friend1.txt

You should see the first friend of the empty directory. touch creates a file if it does not exist. It does also have another use case which is not relevant at this moment.

But wait, our directory which is named empty_house is not empty anymore! Let's fix that by renaming it.

Enter the command cd .. to go one directory back. The two dots .. refer to the parent directory in Linux.

Now that you are back in ~, enter mv empty_house happy_house. Now, enter ls again. You can see that empty_house does not exist anymore. It was renamed to happy_house (since it has at least one friend now). mv stand for move.

But moving is not the same as renaming, right?

Well, mv does move a file or directory to a new destination with the possibility to give it a new name on the destination. So we did move the directory empty_house to the same location, but we did give it a new name.

I know, it is tricky. Let's take a look at an example that does actually move. Enter the command touch friend2.txt friend3.txt. This will create two new files at the same time. This way, you don't have to type touch friend2.txt and touch friend3.txt.

Now, let's move one of our new text files. Enter mv friend2.txt happy_house. Enter ls to see that friend2.txt disappeared. Let's verify that it now lives in happy_house. You could use mv happy_house and then ls analogously to the strategy above. But it is faster to use ls directly with a path as an argument. Enter ls happy_house:

$ ls happy_house
friend1.txt friend2.txt

We verified that friend2.txt was moved. Let's move friend3.txt, too. Enter mv friend3.txt happy_house/loud_friend.txt. Take a look at the content of your directory now:

$ ls happy_house
friend1.txt friend2.txt loud_friend.txt

We did not only move friend3.txt. We did also give it a new name in the destination. Hopefully, you have now a better understanding of renaming and moving with mv.

Remove

What if our house is not really happy anymore since a loud friend did move in? Let's remove that loud friend!

Enter cd happy_house and then rm loud_friend.txt. You will not see any output, but let's see what has changed in the directory:

$ ls happy_house
friend1.txt friend2.txt

The loud friend is removed! rm stand for remove.

Warning ⚠️ : rm deletes a file directly! The file is not moved to a trash! It is gone! You can't just restore it anymore! Think twice before using rm.

Note: Although rm deletes the file from the file system, there is still some chance that the file content still exists on the disk. One could try to recover it with some tools, but it is hard and nothing is guaranteed. Nevertheless, if you want to delete something sensitive for sure, then you have to use a tool that overwrites the file content before deleting it. Physically destroying the whole disk is also an option 🔥😂

Does rm also work with directories? Let's test it:

$ ls
friend1.txt friend2.txt

$ mkdir zombies

$ ls
friend1.txt friend2.txt zombies

$ rm zombies
rm: cannot remove 'zombies': Is a directory

So it does not work. To delete an empty directory, use rmdir:

$ rmdir zombies

$ ls
friend1.txt friend2.txt

rmdir stands for remove directory. But it does only work on empty directories! Let's verify this on none empty directories:

$ ls
friend1.txt friend2.txt

$ mkdir zombies

$ touch zombies/zombie1.txt

$ ls zombies
zombie1.txt

$ rmdir zombies
rmdir: failed to remove 'zombies': Directory not empty

What to do now? Turns out, rm is more powerful than we thought and can delete directories too, even if they are not empty! But you have to give it a flag.

What is a flag? It is an option that you specify after the command name that enables some functionality.

In our case, to remove a directory that is not empty, we need the -r flag of rm:

$ tree
.
├── friend1.txt
├── friend2.txt
└── zombies
    └── zombie1.txt

1 directory, 3 files

$ rm -r zombies

$ ls
friend1.txt friend2.txt

The directory zombies is removed!

You probably wonder what tree is. As you can see in the output above, it shows you the tree of your current directory 🌳 It goes recursively through all directories starting with the current path and shows their content.

Simple file editing

Now, we want to write some rules to avoid having loud people or zombies again.

Let's make sure that we are in our house directory first. To do so, enter pwd:

$ pwd
/home/USERNAME/happy_house

What you see is the path to your current directory (also called working directory). USERNAME here is the name of your user. pwd stands for print working directory.

We could write our rules in a simple text file. But how do we edit files in the terminal?

There are many ways to edit text files in the terminal. The simplest method is to use the editor nano.

Enter the command nano rules.txt. You will be presented with a "terminal window" showing a blinking cursor and some shortcuts at the bottom.

Let's write some rules, for example:

No zombies!
No loud housemates!

How to save and exit? Let's take a look at the shortcuts at the bottom. The shortcuts starting with the symbol ^ expect the Ctrl key. Those starting with M- expect the Alt key. To save, we use ^X which means that we have to press X while holding Ctrl.

Now, it asks us:

Save modified buffer?
Y Yes
N No    ^C Cancel

A buffer is a file that is loaded in the memory (RAM). If you press N, then your edits are lost! In our case, we want to save the rules. Therefore, we press Y.

Now it shows us:

File Name to Write: rules.txt

We want to keep the name that we did specify while calling nano. Therefore, we just press Enter. Otherwise, you can change the name and save the file under another name.

Let's take a look at our rules:

$ ls
friend1.txt friend2.txt rules.txt

$ cat rules.txt
No zombies!
No loud housemates!

We used cat 😺 to only print the content of the file rules.txt without opening it with an editor. cat 🐈️ stands for concatenate. This does not sound like printing file content!? This is because cat 🐱 can be used to concatenate the content of multiple files. But this is not relevant for now.

Manuals

After a while, the house might have many rules, more than the two that we just entered. It would be useful to be able to count how many rules we have. To do so, we can use the command wc which actually stands for word count (not 🚾), but it is able to count more than words:

$ wc rules.txt
2 5 32 rules.txt

We see three numbers. The first one is the number of lines, the second is the number of words and the last is the number of bytes. How do I know that?

I do not memorize everything! I had to look up the meaning of the three numbers.

Where do you look up such things?

You could use the internet, but (almost) every Linux command comes with a manual. To access the manual of a command, we use the command man followed by the name of the command that we want to look up. You probably already guessed it, man stands for manual.

Let's look up the command wc:

$ man wc
NAME
    wc - print newline, word, and byte counts for each file

SYNOPSIS
    wc [OPTION]... [FILE]...
    wc [OPTION]... --files0-from=F

DESCRIPTION
    Print  newline,  word, and byte counts for each FILE, and a total line
    if more than one FILE is specified.
    A word is a non-zero-length sequence of printable characters
    delimited by white space.

    (…)

    -m, --chars
        print the character counts

    -l, --lines
        print the newline counts

    (…)

    -w, --words
        print the word counts

    (…)

(…) indicates that parts of the output were kept out to only show output relevant to our context.

The structure of the output is a standard for command manuals (also called man pages).

The first section of the output is NAME which shows the name of the command with a brief description of what it does.

The second section is SYNOPSIS which shows different ways of using the command. The brackets indicate that a part is optional. The three dots ... (not (…)) indicate that a part can be specified more than one time. This means that [OPTION]... tells us that the command accepts zero to many options.

The options are presented in the section DESCRIPTION which also explains the command but with more details.

Let's pick one option: -l, --lines. The first part -l shows the short version of the option (not always given). The second part --lines shows the long version which is more verbose. The description below tells us that the option prints the newline counts. We can try it out, but first, you might already be in the panic mode because you might not find out how to exit this manual.

HOW CAN I EXIT THIS MANUAL? DO I HAVE TO EXIT THE TERMINAL AND OPEN A NEW ONE? 😱

Don't panic! (Wait until you open Vim)

You can exit the manual by pressing the key q. You are free now 🕊️

Now, let's try the option -l that we got from the manual:

$ wc -l rules.txt
2 rules.txt

$ wc --lines rules.txt
2 rules.txt

You can see that the short -l and long --lines versions are equivalent. They lead to returning the number of lines.

Let's try using more than one option:

$ wc -l -w rules.txt
2 5 rules.txt

We see that we get the number of lines and then the number of words.

We learned how to access and read the manual, but how do we navigate the manual?

If you open a manual with man, you can scroll up and down using the arrow keys. You can search by pressing /, then enter what you are search for, lines for example, and then press Enter.

If you get more than one match for your search pattern, you can jump to the next match with the key n and to the previous one with N (Shift + n).

You can learn more about how to navigate manuals (and other so called pagers) by pressing h in a manual. But since a lot is derived from the editor Vi/Vim, we will learn more about it later when we learn about this editor.

Fun fact: You can read the manual of the manual with man man 😃

Help!

If you want to read a smaller version of the manual, you can run COMMAND --help. Almost every command supports the --help option and its small version -h. You will then get a quick reference.

Try wc --help!

Commands that don't have a man page usually have detailed help messages as an alternative.

Paths

Let's build one more house!

$ cd ~
$ mkdir new_house

$ cd new_house

We did not use any new commands, but what is this symbol ~? We did already mention it and you might have noticed that it was shown in the prompt after opening the terminal. The so called tilde ~ stands for your home directory (home for short) in Linux 🏠️ Your home as a user has the path /home/USERNAME and is the directory where you should place your own files.

By entering cd ~, we did make sure that we are in our "home" before creating a new directory. Entering only cd does have the same effect as cd ~.

So we did create a new house directory and move into it. Let's say we want to copy the rules from the first house to the new one. To do so, we can use the command cp that stand for copy:

$ pwd
/home/USERNAME/new_house

$ cp ~/happy_house/rules.txt .

$ ls
rules.txt

$ cat rules.txt
No zombies!
No loud housemates!

We copied the rules, but did you notice the dot at the end of the command cp? What does it mean?

We learned that the two dots .. refer to the parent directory (one directory back). One dot . refers to the current directory.

Here are some equivalent commands that might help you understand paths in Linux:

  1. cp /home/USERNAME/happy_house/rules.txt /home/USERNAME/new_house/rules.txt
  2. cp ~/happy_house/rules.txt ~/new_house/rules.txt
  3. cp ~/happy_house/rules.txt ~/new_house
  4. cp ~/happy_house/rules.txt .
  5. cp ../happy_house/rules.txt .

All the commands above do the same thing. The difference is the way they specify the source and destination path.

The 1. command is the most verbose one. We specify the full path of the source and destination.

In the 2. command, we use ~ which is a shortcut to /home/USERNAME.

In the 3. command, we remove the file name from the destination path. If a file name is not specified in the destination path, then the file name from the source is used.

In the 4. command, we use the dot . as a shortcut to the current directory since we are currently in the directory new_house.

In the 5. command, we use the two dots .. instead of ~ which is also possible since the parent directory is ~ in this case. The two dots are useful when we are operating in directories that are nested deeper in the home directory.

You might think: . is the path to the current directory. .. is the path of the parent directory. Is ... the path of the parent directory of the parent directory? 🤯 Let's try it out:

$ ls .
rules.txt

$ ls ..
happy_house new_house (...)

$ ls ...
ls: cannot access '...': No such file or directory

So this does not work. Any number of dots greater that 2 doesn't work, except if we use separators. To access the parent directory of the parent directory, we can use ../..:

$ ls ../..
USERNAME (...)

You will probably only see your user name as output, but if the system you are using has more than one user, then names of the other users would be in the output, too. Normally, every user has an own home directory under /home.

The usage of ../.. or even more dots like ../../.. is not recommended since you would have to go multiple directories up in your mind and this does not work well! I would recommend using the full path for paths not in the current . or in the parent directory ...

What we have just learned about paths does not only apply to cp, but also to ls, mkdir, mv and all commands that deal with paths.

One thing has to be mentioned about cp: To copy directories instead of just files, use the option -r to copy recursively like with rm.

Terminal shortcuts

For typing a long path, you can use autocompletion. Go back to the home directory using cd. Let's say that we want to read the rules of the directory happy_house. Type cat hap without hitting enter yet. Now, press Tab and see how the path is autocompleted to cat happy_house/ ✨ Now, type ru and hit Tab again. Then you have cat happy_house/rules.txt. Much faster, right? 🏎️

If you have another directory in your home that is called something like happy_directory, then the autocompletion completes only to cat happy_. Pressing Tab again shows you the possible completion options. Type one or more characters to make an autocompletion possible and then hit Tab again to have the directory name autocompleted.

Often, commands are not long, but you can use autocompletion to complete commands too. If you type ech and then press Tab, you get the autocompletion echo with the space at the end to enter options or arguments. In this case, we did only save entering one character and a space, so echo is not the best opportunity for autocompletion. But this is only a demonstration. Some command names are longer.

You might think that you don't need autocompletion at all. But you should use it. Not only for the autocompletion itself, but for verification, too!

When you type cat hapy_house/ru and then press Tab, you don't get any autocompletion although you would expect it. But did you notice the missing p in happy? 🧐

This is meant by verification. If you don't get an autocompletion although you think that you should, then check what you have typed so far. It is much easier to correct things this way than having to correct them after trying to run the command.

But what if you did run a command with a mistake and you have to correct it? Or what if you just want to run the same command again with small modifications? Do you have to type the whole command again?

Fortunately, no! You can use the up ⬆️ and down ⬇️ arrow keys to navigate through your commands history. Try it out!

If you start typing a command and you notice that you missed something in the middle of the command, you might try to use the mouse and click. No clicks will help you! Instead, use the left ⬅️ and right ➡️ arrow keys.

If you want to go to the beginning of the command, press Ctrl + a. Then you can go back to the end with Ctrl + e.

If you want to close a session quickly, press Ctrl + d. For now, this will close your terminal. Later when we use SSH to access other Linux machines, Ctrl + d will close the connection and bring you back to the prompt of your machine.

Let's write a very small program in Python. Enter nano nonstop.py and type in the following small snippet:

from time import sleep

while True:
    print("You can't stop me, can you?")
    sleep(1)

Now, exit the file while saving the buffer. If you don't know about Python, don't worry. You don't need any real programming skills for this course. All that you have to know is that this program runs forever and prints "You can't stop me, can you?" every second.

You shouldn't write endless loops. This is only a demonstration for a program that is running and you would like to stop.

Enter python3 nonstop.py to run the code.

Annoying, right? To stop a running program, press Ctrl + c. You have to remember this shortcut!

If you are typing a command and want to start over, you can use Ctrl + c instead of pressing Backspace repeatedly.

But wait, Ctrl + c is (normally) used for copying, right?

Not in a terminal! If you want to copy text in a terminal, then select it with the mouse and the press Ctrl + Shift + C.

To paste text into the terminal, press Ctrl + Shift + v.

Why is copying and pasting so inconvenient? It has historical reasons. You have to take it as it is 🙁


It might be overwhelming to memorize all commands, shortcuts and options. If a command is an abbreviation, then knowing what it stands for is very helpful. If you want to use an option but you are not sure which flag it was, then use --help or read the manual with man! Otherwise, you can look up things in this course or using a search engine 😉