Skip to content

Shell Basics

In discussions about the command line, “terminal,” “shell,” and “command” get used interchangeably, but they refer to three distinct layers. Untangling the relationship between them is a prerequisite for understanding why the command line behaves the way it does.

Division of labor: terminal, shell, and command

Section titled “Division of labor: terminal, shell, and command”

A terminal emulator is a GUI program responsible for displaying text and capturing keyboard input — essentially just an input/output window. It has no idea what the input actually means. Common terminal emulators include GNOME Terminal, Konsole, and iTerm2.

A shell is a program that runs inside the terminal, responsible for reading the text a user types, parsing it into concrete operations, executing them, and sending the results back to the terminal for display. The shell is what actually “understands” commands — not the terminal itself. The same terminal program can run different shells.

A command is a line of input given to the shell — it might be a built-in shell feature (like cd), or a standalone executable program on disk (like ls). The shell is responsible for figuring out which one it is and handling it accordingly.

The Bourne Again SHell — the default shell on most Linux distributions, with a long history. Its scripting syntax is the de facto industry standard, making it the one most worth learning first when picking up the command line.

The user@hostname:~$-style text shown when opening a terminal is called the prompt. It isn’t a fixed string generated by the system — it’s a formatted string defined by the PS1 environment variable, and its content is fully customizable (current path, Git branch status, last command’s duration, and similar details are all implemented by modifying PS1). Every time the prompt appears, it means the shell has finished handling the previous command and is waiting for the next one.

A full command execution roughly follows these steps: the shell reads the input text → determines whether it’s a built-in or an external program → if external, searches the directories listed in the PATH environment variable, in order, for a matching executable → spawns a child process to run it → waits for that process to finish, displays its output in the terminal, and shows the prompt again to wait for the next command.

Shells run in one of two modes: interactive or non-interactive. Manually opening a terminal and typing commands one at a time is interactive. Running a script file (e.g. bash script.sh), where the commands inside execute automatically in sequence without waiting for input, is non-interactive. The two modes also load different configuration files — this is why some environment variables set manually in a terminal take effect there but aren’t visible when the same commands run inside a script. The exact order in which configuration files get loaded is covered in the upcoming material on environment variables.

This topic is an important part of building a reliable Linux development workflow. Understanding it clearly will make later tasks easier, because it reduces guesswork and helps you recognize when a step is missing or misapplied.

  • Try the commands or configuration shown here in a safe test environment.
  • Compare how the concepts apply across different distributions or tools.
  • Keep a short note of what worked and what failed so you can diagnose future problems faster.
  • Revisit the related article in the series to deepen the connections between topics.
  • Skipping verification steps and assuming the system is configured correctly.
  • Copying commands without adapting paths, package names, or tool versions for your environment.
  • Treating this topic as an isolated tip rather than part of a larger workflow.