There isn't a sharp border between the shell and the applications.
Some of the commands that you run in a shell have to be built into the shell, because they act on the shell process. For example,
cd changes the shell's working directory, and this can't be done from the outside, so
cd has to be a built-in command. But this is an implementation detail. A casual user doesn't need to know that there are technical reasons that compel
cd to be a built-in command.
At another extreme, there are large applications that are made by different authors, such as Firefox or Emacs. These aren't going to be built into any shell because they're too big. But this isn't a fundamental impossibility, just a matter of design. For examples, there are shells¹ that have builtins to make simple GUI applications.
In the middle, there are commands that could go either way. For example, the
echo command doesn't need to be built into the shell, but almost every shell has it built in because it's very small, and is used often so should be efficient. Another example is
kill, which for casual usage could be an external command, but having a built-in has several advantages: you can invoke it even if you've reached a limit on the number of processes, and you can give it a shell job number (
kill %2) in lieu of a process ID. Even the
[ … ] construct (which can also be written
test) could, in principle, be an external command, but is built into shells for the same reason as
If you're curious, you can check the status of a given command with the
type command. For example, in my setup:
% type while type setenv cp emacs
while is a reserved word
type is a shell builtin
setenv is a shell function
cp is an alias for cp -i
emacs is /usr/bin/emacs
Reserved words such as
then are part of the shell syntax. Builtins are commands that are built into the shell and don't require an external executable. Functions are compound commands that are defined and named by the user, and can be called by their name. Aliases are user-defined short names for longer commands (behaving differently from functions). The last example is an external command.
dtksh. There is no free implementation.