When we talk about the command line in a computer, we seldom refer to a shell — a program that receives typed commands and passes them to the operating system on behalf of the user. Technically, a shell is a macro processor that executes commands. It takes texts and symbols and expands them to create larger expressions. We may also describe it as an interface between the user and the operating system kernel.
A shell has its own programming language. It may be used interactively, receiving a typed input, or in a non-interactive manner, reading commands from a text file. Those commands may be synchronous or asynchronous.
Almost all Linux distributions include a shell developed by the GNU Project, called bash, an acronym for Bourne-Again SHell. But there are others, like the C Shell (abbreviated csh), the Tenex C Shell (tcsh), the Korn Shell (ksh), and the Zero Shell (zsh).
Each user has a default shell, defined in the configuration file /etc/passwd. The Unix command chsh (an abbreviation of “change shell”) may list all the shells installed in a computer and change the default one. Typing, for example, “chsh -l” (“-l” comes from “List”) at the command prompt, we might get a response like this:
$ chsh -l
In this example, the computer has three installed shells: sh, bash, and zsh. Typing, for instance, “chsh -s /bin/zsh” (“-s” comes from Switch), we could change the default shell to zsh, the Zero Shell.
The shell has a small set of built-in commands, inherited from the Bourne Shell and specified in the Posix — a set of standards for Unix-based systems. They are implemented in the shell itself instead of being separate programs. Some examples are pwd, cd, exit, times, exec, export, alias, echo, and source.
A bit of history
In 1964, three organizations – General Electric, Bell Labs (then a division of AT&T), and MIT – joined forces to develop a new multitasking operating system called Multics. In 1969, Bell Labs withdrew from that project. Then, Ken Thompson and Dennis Ritchie, who worked at Bell Labs, started to rewrite Multics, creating a less ambitious but much more practical operating system. It was called Unics, a name that was subsequently stylized as Unix.
Thompson developed the first Unix shell, called v6, in 1971. The basic concept behind it was inherited from Multics, where the operating system was divided into layers. The kernel was the underlying layer responsible for controlling the computer hardware. The shell ran over it, making the connection between the kernel and the user.
That first shell created by Thompson accepted symbols to redirect (<, >, and >>) and to pipe (| and ^) data between commands. That syntax allowed the output of a command to be sent to another command. Modern shells still use it. This is an example:
$ ls | grep bin
In this example, the ls (list) command lists the contents of the current directory. Its output is then piped to the grep utility to search the “bin” string in the content list.
The v6 shell also accepted sequential commands (separated by a semicolon) and asynchronous ones (with the & symbol). For example:
$ rm -rf my_dir && mkdir my_new_dir
This code will delete a file directory called my_dir and create a new one called my_new_dir.
But the v6 shell couldn’t read scripts from text files. It worked only in the interactive mode. So in 1975, Stephen Bourne, also from Bell Labs, developed the Bourne Shell (abbreviated sh), a more advanced version of the shell, capable of executing scripts as well as interactive commands. Bourne added support for loops, variables, and flux control statements in the script language. The sh soon replaced Thompson’s original shell. But it still wasn’t ready to support the creation of functions.
A shell is not a terminal
A shell and a terminal are different things despite being related to each other. A terminal emulator (usually called just “terminal”) is a program that interacts with the shell on a graphic user interface (GUI). Each GUI has its terminal: KDE, for instance, has the Konsole, and Gnome, the Gnome Terminal. Additionally, there are various alternative terminal emulators, like Tilix, Terminator, Guake, and Xterm. However, they all have the same function: providing access to the shell.