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:
Let’s go through CLI basics!
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:
At the very beginning, you should be fine with what is available there in your OS or integrated development environment (IDE).
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.
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. I have used it for a few years, and most of my CLI habits are adapted from it.
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.
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.
You can check your shell with echo $0
:
In my case, it’s zsh
Every shell is a program and can be run directly from another shell. For example:
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:
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.
So, once you have your terminal up and running, how do you use it?
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 by 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:
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, 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:
pwd
shows the current path in which you are running your commands:
cd
changes the directory—by default it goes to the home directory (https://asciinema.org/ recording or screenshot)
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:
Many standard commands come with different options that allow you to modify the program's 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
.
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 the workspace folder:
cd workspace
—changes the current directory to the workspace:
cat file
—shows the file content on the screen:
The meaning of parameters depends on the program—at first, you can expect to need to check the documentation a lot.
Standard output is the text that is added to the command line when you run the program. Its text is 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 the >
operator. Example:
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:
The difference becomes obvious when you redirect the output to a file:
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 allows for scrolling:
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.
Pipes are ways of connecting the standard output of one program with the standard input of another. This is how CLI achieves the interoperability I mentioned in my previous article.
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:
Where:
cat …
—reads files and returns their content in standard output,
less
—gets the value from standard input, and makes it fit the screen
Similarly, by using the search utility grep
:
Where:
cat …
—as above
grep 1
—gets the value from standard input, and filters it to only the lines that contain 1
.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 it to an existing file, you can use >>
instead.
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.
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.
The main trick to being 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 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 differences in arguments.
Manual scrolling is fine for getting one of or a handful of the most recent commands. If you want to get something further from the past, however, you can use the search functionality. By default, the command you can use is CTRL + R to begin a search in your command history:
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.
You can speed up typing even more by using wildcards to match the names of multiple files:
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.
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 arrows up and down to move around the file.
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.
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
:
less
supports other navigation commands similar to what you can find in vim
:
j
—scroll down one linek
—scroll up one linegg
—scroll to the beginning of the fileG
—scroll to the end of the filed/u
—down/up half screen
Those shortcuts will help you navigate quickly through the file.
That’s great! The command line is a great tool to boost your efficiency while programming. You can sign up here to get updates from me as I publish other command line-related materials.
Also published here