The command line remains the most direct way to drive an operating system, one instruction at a time. This article draws the lines between terminal, console, shell, and command line; traces their UNIX and POSIX foundations; compares sh, Bash, zsh, and PowerShell; covers shell scripting; and walks through the main terminal editors.
Terminal, console, shell, and command line
These four terms name different layers of the text interface, and conflating them is a common source of confusion.
As early computers gained interactive electrical interfaces, they needed a way to accept typed commands and print out results. They borrowed the teleprinter, or teletype (TTY), an electromechanical machine originally built for telegraphy that turned electrical pulses into typed text on paper.
By the late 1960s, screens started replacing paper. The Datapoint 3300, released in 1969, was the first commercial video terminal, and it displayed text on-screen instead of printing it, though it still emulated a Teletype Model 33 underneath. Not every terminal worked line by line, though. IBM's 3270, introduced in 1971, buffered an entire screen locally and sent it to the mainframe as one block only when the user pressed an attention key, a model built for high-volume data entry rather than a running conversation with a shell. DEC's VT100 followed in 1978 as Digital's first ANSI-compliant terminal.
DEC VT100 terminal at the Living Computer Museum
Modern terminal emulators like xterm, GNOME Terminal, iTerm2, and Windows Terminal still reference that VT100 model. They render characters, interpret ANSI/VT escape sequences for cursor movement, color, and text attributes, and handle window resizing.
On UNIX-like systems, the emulator and the shell aren't connected directly. A kernel-managed pseudoterminal, or PTY, sits between them, so the shell behaves as if it's talking to real hardware.
A console originally meant the primary system terminal or a physical operator station. In contemporary Linux usage it often refers to those virtual consoles or the system console device. Colloquially it is frequently used as a synonym for a terminal window.
The shell is the command language interpreter that runs inside the terminal, attached to the PTY. It reads lines of input, performs expansions and parsing, executes commands or builtins, manages the process environment, job control, and signals, and writes results back. The shell turns keystrokes into the system calls that create, run, and manage processes.
The command line (or CLI) is the interactive prompt and the style of interaction it enables, typing commands rather than using a graphical interface. It is the visible surface of the shell.
In practice, a terminal emulator is launched, which allocates a PTY and execs a shell; the shell then presents the command line.
UNIX, POSIX, and Linux
UNIX, originating at Bell Labs, established the model of small composable tools, a hierarchical filesystem, pipes for connecting stdout of one process to stdin of another, and a programmable shell. The original Thompson shell gave way to the Bourne shell (sh) in Version 7 Unix (1979); the Bourne shell became the basis for later standardization.
POSIX (IEEE Std 1003.1 and related) defines a portable operating system interface, including a Shell Command Language standardized primarily from the Korn shell (ksh88), itself a backward-compatible superset of the Bourne shell. A POSIX-conforming /bin/sh guarantees a baseline of syntax, builtins, expansions, and utilities so that scripts can move across UNIX-like systems with high reliability. Features outside this baseline are extensions.
Linux provides a UNIX-like kernel together with the GNU userland (or alternatives). Most distributions ship Bash (the Bourne-Again SHell) as the default interactive shell while often linking /bin/sh to a lighter POSIX shell such as dash for speed and strict compliance in scripts. macOS is UNIX-certified and switched its default interactive shell to zsh; Windows offers native PowerShell plus WSL and other UNIX environments. The common POSIX substrate is why shell skills and many scripts transfer across these platforms.
Shells in detail: sh, Bash, zsh, PowerShell
Shells begin by breaking your input into pieces, a process called lexical analysis, then parsing those pieces into commands, pipelines, and lists. Before running a command, the shell substitutes placeholders for their real values, a process called expansion: ~ becomes your home directory, and $variable becomes whatever that variable holds. The shell also expands filename patterns, called globbing, where *.txt matches every file ending in .txt. Shells also maintain the environment, handle redirections, and implement job control, including process groups, sessions, and foreground/background switching (pausing a running command with Ctrl-Z, then resuming it with fg or bg) via signals like SIGTTIN and SIGTTOU. Some of the syntax below will look familiar if you've written code in other languages, but it doesn't always work the same way here.
sh (POSIX/Bourne-derived) is the baseline shell, selected by starting a script with the shebang line #!/bin/sh. Modern /bin/sh is typically dash, ash, or Bash invoked in POSIX mode. It supports the core language: pipelines, command chaining with &&/|| (run the next command only if the previous one exited successfully or failed), if/while/for/case, variable expansion, command substitution $(...) (and the older backticks), here-documents, and basic globbing. It deliberately omits arrays, Bash's [[ ]] conditional (a more capable test syntax than POSIX's older [ ]), process substitution, many Bash-specific parameter expansions, and advanced interactive features. Scripts intended for maximum portability should target this dialect and use #!/bin/sh.
Bash is GNU's upward-compatible implementation of the Bourne shell, meaning anything that runs in sh also runs in Bash, with more added on top. It adds indexed and associative arrays, the [[ ]] keyword test (with richer operators and no word-splitting surprises), process substitution <(...) and >(...), extended globbing, brace expansion, coprocesses, programmable completion (tab-complete that's aware of command context, not just filenames), improved history and Readline editing, and numerous parameter expansion operators. When invoked as sh or with --posix, many extensions are disabled or altered for closer compliance. "Bashisms" (arrays, [[ ]], function keyword variants, etc.) are common sources of non-portable scripts.
zsh (Z Shell) is designed for powerful interactive use while remaining a full scripting language. It incorporates ideas from Bash, ksh, and tcsh, and adds its own. Notable differences and features include:
- Arrays are 1-indexed rather than 0-indexed, as in Bash.
- Extended globbing is richer and enabled more readily, letting you filter matches by file type or exclude patterns directly in the glob itself.
- A sophisticated completion system (
compsys) that supports context-sensitive, multi-level, described completions far beyond Bash's programmable completion. - Spelling correction, shared history across sessions, directory stacks, floating-point arithmetic, and extensive customization via hooks, themes, and modules.
zsh can emulate sh or Bash (emulate sh) but is not POSIX-compliant in its native mode. It is the default on macOS since Catalina and is popular with frameworks such as Oh My Zsh.
PowerShell is a cross-platform shell and scripting language built on .NET (PowerShell 7+). Its fundamental distinction is the object pipeline: cmdlets and expressions pass .NET objects rather than text streams. Downstream commands receive structured data with properties and methods, with no need to parse columnar text with awk/cut. Pipelines use | but operate on objects; common parameters, formatting views, and the type system are first-class. It provides advanced functions, classes, modules, remoting, and Desired State Configuration. Aliases and a help system (Get-Help, Get-Command) ease the transition. While it can invoke external programs and handle text, its strength is object-oriented automation, especially in Windows and Microsoft cloud environments.
Choosing which shell to use typically comes down to the job at hand. For portable scripts and container entrypoints, POSIX sh, or Bash run in POSIX mode, is usually the safer choice. When interactivity and richer features matter more, zsh, or a heavily configured Bash, tends to serve better. For Windows-centric or object-heavy automation, PowerShell is often the right fit. Most systems support several shells side by side, so the shebang line, or however the shell is explicitly invoked, decides which one runs a given script.
Shell scripts
A script is a text file of commands beginning with a shebang (#!/usr/bin/env bash or #!/bin/sh). When you run the file, the kernel reads that first line to find and launch the named interpreter, then hands it the same file to read from the start. Since a line starting with # is a comment, the interpreter skips the shebang line without ever executing or printing it. A script also runs non-interactively, which the shell decides automatically from how it was started rather than from any command you give it: no prompt, no one typing commands one at a time. It inherits or modifies the environment, performs the same expansions as an interactive session, and can set options up front, like set -euo pipefail in Bash for stricter error handling. Traps, which catch signals like Ctrl-C and run cleanup code instead of letting the script just die, and redirections work the same as they do interactively. Job control, though, is off by default in scripts; turning it on with set -m still won't let fg bring a job to the foreground without an attached terminal. For complex data structures or performance-critical logic, higher-level languages are often preferable, but shells excel at orchestrating existing tools via pipelines and simple control flow.
Terminal editors: nano, Vim, Emacs
Remote or minimal environments require editors that run inside the terminal, attached to the same PTY.
nano (GNU nano) is a modeless, beginner-oriented editor. Key bindings are shown at the bottom of the screen, including Ctrl-G for help, Ctrl-O to write out, Ctrl-X to exit, and Ctrl-W to search. It supports syntax highlighting, soft wrapping, undo, and basic regular-expression search-and-replace. It is lightweight and requires almost no learning investment for simple edits.
Vim (Vi IMproved) is a modal editor descended from vi. Normal mode is where you navigate and issue commands built from operators (d, y, c), motions, and counts. Insert mode is for typing text directly. Visual mode selects text by character, line, or block. Command-line mode, entered with :, handles writing, quitting, substitution, and other operations that don't fit as single keystrokes. A handful of other modes exist for more specialized cases, including Replace and Terminal-Job. Efficiency comes from composable operators and motions, macros, marks, and a rich plugin ecosystem. The learning curve is steep; vimtutor and the extensive :help system are the standard entry points. Vim (or a vi-compatible binary) is nearly ubiquitous on UNIX-like systems.
Emacs is an extensible, self-documenting editor built around a small C runtime with an embedded Emacs Lisp interpreter; most of its actual editing behavior is implemented in Emacs Lisp on top of that. Everything is a buffer; windows and frames display portions of buffers. Keymaps bind key sequences, frequently involving Control and Meta, to commands. Major and minor modes specialize behavior for programming languages, Git (via Magit), Org-mode, and more, and it can be extended into a full environment. The philosophy emphasizes "everything is a buffer, a Lisp object" rather than strict modality, though Evil mode provides Vim emulation for those who want it. GNU Emacs is the primary, most widely used implementation.
For quick remote edits, nano is often sufficient. Sustained terminal-centric work usually favors Vim or Emacs; both repay investment with efficiency and customizability. All three are available through standard package managers and on virtually every UNIX-like system.
Closing notes
A terminal emulator today does the same job a teletype did many years ago. It takes what you type and shows you what comes back. The shell, the completions, the object pipelines around it have all grown to match what the underlying systems now do, but underneath all of that, the terminal is still what it's always been: a channel through which a person and a machine communicate. The documentation and resources listed below can help, but really getting to know a place, the terminal included, comes from spending time in it. Go try it. cd around, ls what's there, echo something back at yourself, and reach for --help or man when you get stuck or want to know more.
Selected references
- Red Hat, "Terminals, shells, consoles, and command lines"
- The Valuable Dev, "A Guide to the Terminal, Console, and Shell"
- GNU Bash Reference Manual
-
zshdocumentation (zsh.sourceforge.io) - Microsoft Learn: PowerShell overview and about_Pipelines
- Open Group, POSIX Shell Command Language
- O'Reilly, "The IEEE 1003.2 POSIX Shell Standard"
- Computer History Museum: VT100 Terminal, Datapoint 3300
- vt100.net, "Digital's Video Terminals"
- Wikipedia: Teletype Corporation, Datapoint 3300, IBM 3270, System console, Bourne shell
- Linux man-pages (man7.org): pty(7), termios(3), tty(4)
- GNU nano, official cheatsheet
- Vim documentation, intro.txt
- GNU Emacs manuals
- Greg's Wiki, Bashisms, and related POSIX portability notes


Top comments (0)