What’s what
Most users of personal computers today are intimately familiar with the graphical user interface (GUI) where interactions with the computer typically involve using a mouse (and sometimes the keyboard) to click and navigate through windows, icons, menus, and buttons.
Before GUIs became common, computers were often operated through a text-based method called a command-line interface (CLI). And this approach is sill widely used today.
In the “old days,” most computers would boot into the CLI because there was no graphical altnernative. Today, every major operating system still includes a way to access the command line through an application called a terminal emulator (or just terminal for short). On macOS, the app is unceremoniously named “Terminal” and can be found in the /Applications/Utilities directory. But you can download other terminal applications, including iTerm2, Warp, Alacritty, Hyper, Tabby, Kitty, Rio, or others.
Every terminal application has a text-based input field called the command line that begins with a prompt (usually > or $). When you type and submit a command, the Shell Command Line Interpreter (or just Shell) parses and interprets the text you have typed, carrying out your instructions and possibly returning information to you in the terminal. This Read-Eval-Print loop (REPL) is common when computer programs allow “live” interaction between the user and computer.
The default shell on macOS at the time of writing is zsh (pronounced the “Z shell”) which replaced bash (the “Bourne Again SHell”) as the macOS default starting with the release of macOS Catalina in 2019. bash, as evidenced by its name, was an evolution of the Bourne shell (with the short name sh). To round out the list, the only other popular shell today is fish (the “friendly” shell).
Shell Basics
First, let’s determine what shell you are using. Open your terminal application and type echo $SHELL at the command prompt. If the response is /bin/zsh then its zsh.
Most commands tend to have the following structure
[command] [options] [arguments]
You’ll need help. Often. The commands run-help and man (short for manual) following by a command name will bring up the command’s documentation using the terminal pager less. For navigation, arrow keys move one line at a time, page up/down and the spacebar move one page at a time, and q exits. For more succinct documentation, visit https://tldr.sh/ in a browser, which can be used interactively or downloaded.
Moving around
Navigating the hierarchy of directories and performing simple operations on files are fundamental to working from the command line. Note that many of the following tools take the verbose -v option, which prints a confirmation message in the terminal and is useful to “see” what these commands do, especially while learning them.
pwdprints the current (working) directorycdchanges the working directorylslist the contents of a directory..denote the parent directory.denotes the current directory (useful, eg, when copying)
Creating, moving, copying, and deleting files and directories are common operations:
touchupdates the access and modification times of files, but also creates a file if it does not yet existmvmove (or rename) one or more files or directoriescpcopy one or more files or directoriesrmremove (ie, permanently delete) file(s). A good alternative is to “trash” them withmv file_name ~/.Trashmkdircreate a new directoryrmdirremoves directories (use with caution!) A good alternative is to “trash” them by installing the trash command withbrew install trashand then runningtrash dir_name
It is often useful to use wildcards to return a “group” of files. Common wildcards include:
*denotes zero or more characters?a single character[abc]a list of permited characters[a-z]a set of characters
Editing Text at the Command Line
When working in a terminal, you’ll often need to edit what you’ve typed, e.g., to fix a typo, move back a few words, delete a chunk of text, or recall and modify a previous command. While you can do this with arrow keys and backspace, you’ll become dramatically faster once you learn a handful of editing shortcuts.
Most shells (including zsh and bash) provide “line editing,” meaning you can edit the current command before you run it. These editing features come from a library called readline (used by bash) or a similar system called zle (the Zsh Line Editor). Both support two classic styles of keybindings: Emacs-style editing (the default in most shells) and Vi-style editing (popular among Vim users). These styles trace back to two influential text editors from the 1970s: Emacs and vi, which shaped how programmers interact with text even to this day.
Emacs-style keybindings (default)
In Emacs mode, you use Control key combinations to move and edit efficiently. These are widely supported across shells and many terminal programs. Here are the most useful ones to memorize. Note that on the macOS Terminal, “Alt” is often the Option key.
Ctrl-Ajump to the beginning of the lineCtrl-Ejump to the end of the lineCtrl-Bmove back one letterCtrl-Fmove forward one letterAlt-BorEsc-Bmove back one wordAlt-ForEsc-Fmove forward one wordCtrl-Lclear the screenCtrl-Udelete from cursor to the beginning of the line (“undo this whole front part”)Ctrl-Kdelete from cursor to the end of the line (“kill to end”)Ctrl-Wdelete the word behind the cursorCtrl-Pprevious command (same as up arrow)Ctrl-Nnext command (same as down arrow)Ctrl-Rreverse search through history (Start typing part of a previous command and press Ctrl-R repeatedly to cycle matches.)
Vi-style keybindings (modal editing)
Vi mode is “modal,” meaning you switch between modes: “Insert” mode where you type normally, or “Normal” mode where keys perform editing commands. This feels strange at first, but you can become extremely fast once it clicks. Vi’s reputation is that you can move mountains in a few keystrokes, but with the cost that even simple operations also require a few keystrokes.
To change from the default emacs-style key binding to vi-style for the current shell session, run bindkey -v or set -o vi. To enable vi-style keybinding every time you start an interactive shell, add one of those commands to your shell configuration file (typically ~/.zshrc for zsh or ~/.bashrc for bash). Then either restart your terminal or reload the configuration with source ~/.zshrc.
Once enabled, when you’re typing a command you’re usually in insert mode. Press:
Escswitch to normal modeireturn to insert mode at the cursorareturn to insert mode after the cursor
In normal mode, a typical operation folows the pattern count-operator-motion/object. For example, 3dw deletes forward three words. Omitting the count is typica, for example ci( changes the text inside the current set of parentheses. Common commands include:
Movement of cursor
h/lleft/right0beginning of line$end of linewforward one wordbback one word
Editing (normal mode)
xdelete character under cursordwdelete a worddddelete the entire linecwchange a word (delete word and enter insert mode)Ddelete from cursor to end of line
History search
j/kup/down/textsearch backward in history for “text”nrepeat the last search
A common workflow looks like: type a command; hit Esc; quickly edit with w, b, dw, etc.; press i to insert again; run.
Combining tools
The Unix philosophy is that command line tools are designed to do one thing and to do it well. Therefore, complex operations are created through a composition of tools. This is made possible by managing the communication streams of these tools. Each has 3 standard communication streams: standard input (stdin), standard output (stdout), and standard error (stderr). Often, the keyboard will not be the source of input, but rather it will be from the output generated by other tools and contents of files.
<takes input from a file (eg,< file.txt wc)>directs output to a file and overwrites (eg,ls > dir_contents.txt)>>directs output to a file and appends|pipes output from one command to input of another (eg,ls | less)
Common tools for inspecting files, or for gathering and summarizing their contents include:
catfor concatenating files; can be used to print file contents in the terminal for short filesfindfor recursively searching a directory hierarchy returning names of files and/or directorieswcfor counting characters, words, and linesheadfor obtaining the first few linestailfor obtaining the last few linessortfor sorting the contents of a fileuniqfor removing adjacent duplicates
More-advanced tools that deserve their own section and explanation
grepfor matching a Regular Expression pattern in one or more filesseda stream editor for modifying dataawka data processing language named after its creators
Regular Expressions
Sections to add
- File permissions (read/write/execute)
- A whole section on each of grep/sed/awk
- Connecting: ssh/ftp/curl
- Environment variables (incl. customizing the prompt)
- Writing programs (incl. if/for/while)