Skip to contentSkip to navigationSkip to topbar
Rate this page:
On this page

A Beginner’s Guide to the Command Line


If you're an experienced developer who knows your system inside out, this guide is not for you. However, if you've only ever used desktop tools, or you're just starting as a developer, you may not have needed to work at what is variously called "the command line", "a console," or "a terminal". If these terms are unfamiliar to you, or they kind of ring a bell but you're not sure what they are, read on!

The macOS Terminal showing the commands introduced below.

Computer control

computer-control page anchor

Back in the dim and distant past, computers were controlled with typed commands. Then we evolved the Graphical User Interface (GUI) and typing was superseded by pointing and clicking. That's how most folks work with computers today, though often they use a finger on a touchscreen rather than a mouse on a desk.

Computers can still be controlled by entering commands on the keyboard and, as you'll have guessed, this takes place at the command line. Windows, macOS and Linux all have facilities for presenting you with a command line. Typically, these applications are called consoles or terminals.

On macOS, for example, the app is Terminal. You'll find it in Applications > Utilities. Different versions of Linux offer different terminal apps, but they'll be called something like Terminal and be accessible from the desktop. Windows 10 has Windows Terminal; older versions have a Command Prompt entry in the Start menu which calls up their terminal app. Microsoft also has Windows Subsystem for Linux(link takes you to an external page), which implements a Linux command line in Windows 10.

A terminal is just a presentation mechanism; the software doing the real work is called a "shell". That's why you might see PowerShell in your terminal window on a Windows PC. The shell is the real interface between you and the computer; the terminal just displays the shell's output in a window and sends your key presses to the shell.

If you've used a Linux computer that has been configured not to start up a desktop screen, you've been using the command line all along and communicated directly with a shell. Terminal apps are generally only used from a GUI's desktop.

Seasoned developers have favorite shells, but at the start, it's best to make use of the one your operating system provides. Once you've got the gist of how it works, and have begun making use of it, you can start to explore the alternatives.


However, when you invoke a shell, you'll see what's called a "prompt", the shell's cue to you to type in a command. When the command has been completed, you'll see the prompt appear again: the shell is telling you that it's ready for its next task.

There are many different shells, so you may not always see the same prompt when you use multiple machines. The most common Linux shell is called Bash(link takes you to an external page); its standard prompt is the $ symbol. macOS recently began using the Z Shell(link takes you to an external page), which uses % as its prompt. On Windows, the prompt is usually a >. Whatever the symbol, and whatever information is displayed alongside it — often the current directory, but you might also see the drive letter, the name of the logged-in user, or the date — the prompt tells you the shell is waiting for input.

Current directory? This is another common term read in discussions concerning the command line. You might also see it called the "working directory". "Directory" is just shell-speak for the folder, "working" the one you're currently viewing in the terminal.


Files, directories, and their paths

files-directories-and-their-paths page anchor

The sequence of directories in which a file or a directory is located is called its "path". Here's a macOS example:


_10
/Users/Twilio/GitHub/scripts/imageprep.sh

This is an "absolute" path: it identifies precisely where the file imageprep.sh is to be found. Linux and macOS use the /symbol, as shown above, to separate files and directories in the path, but Windows uses \ so just replace one with the other in this and the following examples if you're using Windows Terminal or PowerShell.

Depending on your shell, you may be able to use "relative" paths — paths that depend on where you are starting from. These use the following markers:

  • . — the current directory.
  • .. — a parent directory.

So if we're working in the directory /Users/Twilio/Documents/websource/ then we can access the script — the .sh file — mentioned above using the relative path:


_10
../../GitHub/scripts/imageprep.sh

This means 'go up to the parent directory' (ie. Documents/), 'go up to the next parent directory' (Twilio/), then 'go down to GitHub/scripts/imageprep.sh'.

If you're wondering what the / right at the start of the first path is, it's special: it's the Linux and macOS "root" directory, ie. the top-most directory from which all other branches.

You may see a ~ (called a tilde) in a path. It's one of the Unix shells' shorthand codes: it means the current user's home directory and you can use it anywhere you might otherwise write your home directory's path out in full. It's also a good way of referring to home directories in scripts that will be used by different folks: they all have different home directories, but ~ will be read by the shell as the right one every time.

To run the script imageprep.sh, you must provide its name at the prompt. If it's in a different directory from the one in which you're working, provide an absolute or relative path. If it's in the working directory, you can omit the path. However, you will need to tell the shell that the file is here: prefix it with ./ to indicate the current directory:


_10
./imageprep.sh

(information)

Info

It's outside of the scope of this guide, but it's useful to know that Linux and macOS shells have a variable called $PATH that tells them where to look for files: it contains a list of directory paths. If you type just imageprep.sh, the shell will only look for the file in the directories included in $PATH. That's why we need the ./ above — /Users/Twilio/GitHub/scripts not listed in $PATH.

When referencing shell variables (though not when setting them), always prefix their names with the $ sign.


If you open up a terminal now, when the prompt appears enter one of the following commands:

PlatformCommand
macOS/Linuxls
Windows TerminalDIR

These commands tell the shell to list the files and sub-directories within the current directory, also known as the working directory. How can you see what that is? With another command of course:

PlatformCommand
macOS/Linuxpwd
Windows TerminalCHDIR

To create a new directory, use the following command:

PlatformCommand
macOS/Linux/Windows Terminalmkdir <directory_path>

If the value you put in place of <directory_path> is just the new directory's name, it will be created in the working directory.

To move or "change" to another directory, use the following commands:

PlatformCommand
macOS/Linuxcd <directory_path>
Windows TerminalCHDIR <directory_path>

There are literally dozens of commands you can enter, far too many to list here. There are lots of online resources that list them — just use your favorite search engine.


Arguments: information for commands

arguments-information-for-commands page anchor

Most commands are more than a simple word — you can provide extra information in the form of "arguments" placed after the command and separated by at least one space. Arguments might include target filenames or the location of the directory where the command's results will be placed.

The need to separate arguments with spaces means you need to take care with file and directory names that contain spaces. Telling a shell to treat included spaces as part of an argument and not a separator is called "quoting". For example, to stop the second space in the command


_10
cat /Users/Twilio/my file.txt

from causing errors (specifically cat: /Users/Twilio/my: no such file or directory and cat: file.txt: no such file or directory), you wrap the argument in quotes:


_10
cat "/Users/Twilio/my file.txt"

This correctly displays the contents of the named file.

Other arguments govern how the command works: they're called "switches", "flags" or "options" and are prefixed with - or --. For example, you might issue the ls command mentioned above with these two switches:


_10
ls -l -a

Respectively, these cause ls to output its list in columns (-l) and to include hidden files (-a). The ls command allows you to combine switches into a single statement:


_10
ls -la

This has the same effect as the previous example but is more compact. Many commands work this way, but not all do. Many commands have the switches -h and/or --help which will cause them to output guidance — these will tell you if the command supports combining switches and flags this way.

Remember the mkdir command we mentioned earlier? If you provide a full path as an argument and that includes directories that don't exist, mkdir will display an error message. However, if you also include the -p switch, mkdir will also create any 'missing' directories within the path.


Some shell commands are built into the shell itself, but many more are programs in their own right. Others are "shell scripts". These are what make the command line so attractive to developers. Scripts are a way to combine multiple commands with variables and flow logic to automate key tasks.

Here's an example: if you're building a website, you might write a script to automate all the repetitive setup work you need to do when you test a change: process the style sheets, minify your CSS and JavaScript files, organize the content and transfer it to the location from which it will be served, and to start up the HTTP server.

Or you might write a script to extract certain data points from a stack of log files. Or to package apps ready for distribution. Or… well, the options are endless. Shell scripting is a truly powerful way of automating processes.


Let's look at the first example. Here's the code:


_20
# Rebuild Hugo-generated website 2.3.1
_20
_20
# Set variables
_20
source="$GIT/website"
_20
_20
# Move to the source directory
_20
cd "$source" || exit 1
_20
_20
# Zap any existing build
_20
rm -rf public
_20
_20
# Generate CSS
_20
"$source/scripts/css"
_20
_20
# Build the site
_20
if hugo; then
_20
cd public
_20
rm $(find . -name .DS_Store)
_20
gsutil rsync -d -R . gs://www.example.com
_20
fi

Most lines in a script are read and handled as if you'd keyed in at the prompt; a couple of others determine how the script is run, delimit code structures, or are comments. You can spot all the comment lines: they start with # — shells ignore any text after that symbol, up to the end of the line. Let's go through the rest.

The first real line sets the value of a new variable, source. Don't read the quote marks as string delimiters — they're being used for quoting. Why? Because the value of the variable GIT may contain spaces we want the shell to handle them correctly. GIT is a variable set outside of the script; to read it back we prefix it with $, as we do when we later read back source. Not including spaces on either side of the assignment operator, =, is a requirement in shell scripting.

The command cd we know already: it makes the named directory (the value of source) the current directory. The || symbol stands for 'logical OR' and essentially tells the shell to check the outcome of the command and, if it fails, to run the rest of the line. In this case, that means we exit the script with an exit code of 1, i.e., a failure. The exit code for success is 0. Why check? Because if the target directory doesn't exist, we want to make sure we don't continue.

The command rm is short for 'remove' — it deletes the named file or directory. Because public is a directory (which we might have made earlier), we need to include the switches -f and -r to force rm to delete the folder if it contains any files and to go into and directories it contains and delete them too. You'll need -r whenever you rm a directory.

Remember, lines in a script are processed as if they were entered at the prompt. "$source/scripts/css" just runs the named script, css, to prepare the site's style sheets.

The last section shows some control logic: the script runs the program hugo and if the program runs successfully — its exit code is 0 — the lines inside the if… fi structure are executed.

If hugo runs successfully — it's a static website builder — the script switches to the public directory (hugo is responsible for creating this) and then removes some files that may have been copied in but which we don't want. The $(...) formatting tells the shell to run the code in the brackets and return whatever that code outputs. The output, which is either nothing or a list of files, is passed to rm as an argument — the files we want deleted. The find command is passed . to tell it to look in the current directory; the -name flag and its value, .DS_Store, tell find to look for files of that name.

Finally, we call Google's gsutil tool with a number of arguments to sync the contents of public, ie. the build website files, with a Google Cloud Platform web server.

And we're done — we've built our static website and synced any new files with the web server!

If the script is called deploy.sh, we run it, as we saw before, by entering ./deploy.sh at the prompt. If you'd just created this script in a text editor, you'd first need to make it executable — for which you use the chmod command and its +x (for 'add execute permission') argument :


_10
chmod +x deploy.sh


We've just scratched the surface of the command line, shells and scripts. Hopefully, you now understand what these terms mean, and why developers make them key components of their toolkits. You may already be thinking about how you can do the same.

To learn more about specific commands, Linux and macOS provide a shell-accessible command called man which you provide a command as an argument. It will output the "manual" for the specified command — hence the name. Use the arrow keys to move up and down through the text, and hit Q to quit.

The Linux Documentation Project has a great guide to getting started with the Bash shell(link takes you to an external page) and a more detailed guide covering advanced scripting(link takes you to an external page). There is also the Bash Manual(link takes you to an external page).

For Mac users, there's an equivalent manual for the Z Shell(link takes you to an external page). Check out Apple's Terminal User Guide(link takes you to an external page) too.

Microsoft has its own guides for Windows Terminal(link takes you to an external page), PowerShell(link takes you to an external page), and Windows Subsystem for Linux(link takes you to an external page).

We can't wait to see what you script!


Rate this page: