The Hitchhiker’s Guide to the Command Line
Tags: cli, unix, beginners
Published: 2023-01-18 06:25:09

There are many good arguments for getting used to the command line interface (CLI). However, as a complete beginner, it can be difficult to start, and a new shell session can feel a bit intimidating:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kglpqe87glvq456kvklt.png)

Let’s go through CLI basics!

## Where to start

The first thing you need is a terminal emulator: a program that emulates the text-only access to your machine. Any operating system (OS) will have a big choice of emulators: they are all pretty similar, and the main differences will be
* the number of colors supported,
* available options for font types, size, or color schemas,
* key shortcuts for increasing font size, etc.

At the very beginning, you should be fine with what is available there in your OS or integrated development environment (IDE).

## Shells

Shell is a program that interprets your commands and runs programs for you. It’s a different thing than the terminal simulator we talked about above. In a way, in your graphic interface, you open the terminal, and inside the terminal you have a text-only interpreter of commands. There are many options available, with subtle differences that can alter the user experience a lot.

### Zsh

Z shell, or Zsh, is a modern and popular command interpreter. Its interface is user-friendly, and there are community packages available that allow you to customize your shell experience: [Oh My Zsh](https://ohmyz.sh/). I have used it for a few years, and most of my CLI habits are adapted from it.

### Bash

Bash is a slightly older alternative to Zsh. It’s very common, so you can expect it to be available on many machines that you’ll encounter out there. Many shortcuts from Zsh work there too, but it’s using different configuration files, and the scripting language is a bit different.

### SH

The standard shell. It’s part of the standard Unix commands, and it’s mostly guaranteed to be on any Unix-like machine you will find. Therefore, it’s a safe bet when it comes to writing scripts. The user interface lacks many modern improvements, so I wouldn’t use it for anything besides wiring scripts. 

### What is my shell anyway?

You can check your shell with `echo $0`:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ulbyhep53eedod6lapqk.png)

In my case, it’s `zsh`

### How to change your shell

Every shell is a program and can be run directly from another shell. For example:

{% asciinema 552236 %}

In this way, you can check what shells you have installed and test them quickly. To change the shell permanently, you can use the command `chsh` (change shell), in both Linux and macOS:

{% asciinema 552238 %}

If you lack the shell you want to use, you need to install it first—the exact command depends on your OS or Linux distribution.

## Building blocks

So, once you have your terminal up and running, how do you use it?

### Commands

CLI allows you to run commands by typing their name in the terminal and pressing enter. Each command is a separate program that offers an extensive interface, and each comes with its own documentation. Likewise, each OS brings its own set of commands, but they share similarities—especially with systems inspired with Unix, macOS and Linux. On Windows, the standard command line `cmd` has a very different set of commands, but there are many options available to get a similar interface there as well:
* Native Windows Subsystem for Linux
* Git BASH provided by Git for Windows

Unix was an OS that became publicly available in 1973, and it influenced plenty of things that came later. Its current specification defines [161 commands](https://en.wikipedia.org/wiki/List_of_Unix_commands), but luckily you only need a handful of them to benefit from CLI.

Example of commands:
* `ls` list files in a folder—by default, it shows the contents of the current folder:



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9e23mffg708x07jbho8y.png)

* `pwd` shows the current path in which you are running your commands:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/52h2uilvheib6galyr73.png)

* `cd` changes the directory—by default it goes to the home directory
(https://asciinema.org/ recording or screenshot)

{% asciinema 552245 %}

### Arguments

Each command can take additional arguments. Arguments are space-separated values that come after the command name. The meaning of the arguments depends on the program. You can read about the different arguments in the command documentation:

{% asciinema 552246 %}

#### Options

Many standard commands come with different options that allow you to modify the program behavior. For example, `ls` is very often used with the following options:
* `-a`—to show all files, including ones that start with `.`—a Unix convention for hidden files 
* `-l`—show files in the long format—providing more information

A common convention is to allow options as separate parameters, `ls -a -l`, or combined into one parameter, `ls -la`.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bkwicw3xx6q21xr51t5f.png)

#### Parameters

A parameter is an argument that provides a value to the command, or one of its options.

So for instance, with the example from above, you can provide a path to change the default behavior:

* `ls workspace`—lists files in workspace folder:

{% asciinema 5522469 %}

* `cd workspace`—changes current directory to workspace:

{% asciinema 552250 %}

* `cat file`—shows the file content on the screen:

{% asciinema 552252 %}

The meaning of parameters depends on the program—at first, you can expect to need to check the documentation a lot.

### Standard output

Standard output is the text that is added to the command line when you run the program. It’s text shown by the happy path of the execution. The examples we’ve seen so far have shown the standard output of different commands. 

When learning C++, one of the first things you learn is `cout`—the standard output.

By default, the standard output is just shown on the screen, but you can easily redirect it to a file with `>` operator. Example:

{% asciinema 552254 %}

### Error output

Error output is where programs display information about issues encountered during execution. While running commands directly from the terminal, error output and standard output are treated the same—they’re just displayed on the screen. For example, when I try to `ls` a non-existing file:



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xhd0uxg9wud6fympkprm.png)


The difference becomes obvious when you redirect the output to a file:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t71kswffabsa4l2certa.png)

### Standard input

In a normal workflow, standard input is what you type into your program. The commands we’ve seen so far are not typically used in an interactive mode. A simple example can be a `man` page that allow for scrolling:

{% asciinema 552244 %}

For those with C++ experience, you’ve heard this term for `cin`:
```
cin >> variable;
``` 

For many common commands, the standard input becomes especially important because of the pipe operator.

### Pipe

Pipes are ways of connecting the standard output of one program with the standard input of another. This is how CLIachieves the interoperability I mentioned in my [previous article](article 1 of the series). Using pipes allows you to combine different commands in plenty of creative ways—I’ll be showing some examples later in this series. For now, a simple example is:

{% asciinema 552256 %}

Where:
* `cat …`—reads files and returns their content in standard output,
* `less`—gets the value from standard input, and makes it fit to the the screen

Similarly, with using the search utility `grep`:

{% asciinema 552258 %}

Where:
* `cat …`—as above
* `grep 1`—gets the value from standard input, filter it to only the lines that contains `1`.

### Writing to files

We have already mentioned the `>` operator, used to write the standard output of a command to a file. This operator **overrides** the file with the output we provide. If you would like to **append** to an existing file, you can use `>>` instead.

## Working directory

Everything that happens in the command line is done in the context of a specific disk location—a working directory. When you specify relative file paths—for reading or writing—they are resolved from the working directory. Usually, you set your working directory to a top folder of the project you are working on. When you start a new session, usually the working directory is set to your home directory.

## Running commands

Shell interpreters offer you many shortcuts to speed up your work. With time, you’ll start using them intuitively, without thinking about them. Often when I screen-share with beginners, I’m reminded that those shortcuts are nothing but obvious—below I’ll show you a few productivity tricks for working with the command line.

I’m using Zsh myself, and these shortcuts work there. At least some of them should work in Bash, too, but it can depend on the exact version and configuration.

### Don't type twice—use arrows

The main trick to be fast with CLI is not typing everything all the time. The most basic case is to get back a command you’ve run a few lines before. You can do so by pressing the up arrow key. With arrow up and arrow down, you can scroll through the recent commands, and once you find a one similar to what you want to run now, you can edit it. This speeds up the whole process a lot because you often run similar commands, with some tiny difference in arguments.

{% asciinema 552259 %}

### Search older commands

Manual scrolling is fine for getting one of or a handful of most recent commands. If you want to get something further from the past, however, you can use a search functionality. By default, the command is you can use CTRL + R to begin a search in your command history:
 
{% asciinema 552260 %}

### Use <tab> to autofill

You don’t have to type the entire commands you would like to run. Both Zsh and Bash support the tab key as a way of asking for autofill—they will fill up the command or file name if they are unique or show you all the available options if what you type matches many possibilities. Zsh provides autofill for command options as well.

The autofill is a great feature on two levels: it helps you save time on typing, and it reduces mistakes. As you learn CLI, you should make sure to get into the habit of using autocomplete as much as possible.

{% asciinema 552261 %}

### File names wildcards

You can speed up typing even more by using wildcards to match the names of multiple files:

{% asciinema 552262 %}

## Pager—less

Often, when a program has so much output that it doesn't fit into the screen, it uses another program as a pager—a tool that lets you navigate the output and scroll up and down. Most often the program used for that is `less`. There are a few things worth noting when you use it.

### Simple scrolling

First and foremost, don’t scroll with the scrollbar provided by your terminal emulator. `less` redraws the whole screen of text at the end of the output. If you scroll up inside the terminal emulator, you will see what was returned by other programs before, not the contents of the file you want to read. Instead of scrolling with the scroll bar (scroll wheel) use arrow up and down to move around the file.

{% asciinema 552264 %}

### Exit

Another common point of confusion—how do I leave now? You can leave the full screen mode of ‘less’ by pressing `q`. It’s often styled as `:q` because other programs (for example `vim`) use `:` to start a command.

### Searching

In the command line, everything is text, and text is straightforward to search through. You can search inside the content shown by less by typing `/<search term>`, and navigate through results by typing `n` and `N`:

{% asciinema 552266 %}

### Fancy scrolling

`less` supports other navigation command similar to what you can find in `vim`:
* `j`—scroll down one line
* `k`—scroll up one line
* `gg`—scroll to the beginning of the file
* `G`—scroll to the end of the file
* `d/u`—down/up half screen

Those shortcuts will help you navigate quickly through the file. 

## Are you interested in learning more?

That’s great! The command line is a great tool to boost your efficiency while programming. You can sign up [here](https://how-to-dev.ck.page/5ae2eeba1c) to get updates from me as I publish other command line related materials.