Image of a cookbook.
Photo attribution here.

In our examination of the RBENV shim, we encountered the set command. At that point, we hadn't yet encountered that command, and so we had to look it up in the docs.

In many cases, we can find the manual for various terminal commands using the man command (short for "manual"). If we fail to find what we're looking for using man, we can try checking StackOverflow or another source. But the quality of those sources can vary widely, so a useful habit is to stick to official docs when we can.

Also note that set is a builtin command and therefore we have to access its docs via the help command. Typically, we'd start our docs search with the man command and switch to help if we discover that the command in question is a builtin. A bit later in this post, we'll look at how to tell whether a command is a builtin command or not.

man entries can be hard-to-parse if you've never encountered one before. Let's learn how to read them.

Looking up a man page

One terminal command that most of us are familiar with by now is ls, which prints out the contents of a directory. ls is an internal command (i.e. not a builtin), so let's use it as a springboard to help us learn about man pages.

If we type man ls in the terminal, the result that we get starts out like this:

LS(1)                                                             General Commands Manual                                                            LS(1)

       ls – list directory contents
       ls [-@ABCFGHILOPRSTUWabcdefghiklmnopqrstuvwxy1%,] [--color=when] [-D format] [file ...]
       For each operand that names a file of a type other than directory, ls displays its name as well as any requested, associated information.  For each
       operand that names a file of type directory, ls displays the names of files contained within that directory, as well as any requested, associated
       If no operands are given, the contents of the current directory are displayed.  If more than one operand is given, non-directory operands are
       displayed first; directory and non-directory operands are sorted separately and in lexicographical order.
       The following options are available:
       -@      Display extended attribute keys and sizes in long (-l) output.


Here we can see:

  • the command's name and a brief description
  • a synopsis of the command's usage (the order in which you'd type the command, its flags and arguments, etc.)
  • a longer description of the command itself (here, "operand" means the argument you pass to ls)
  • a list of the command's possible arguments and flags, and what each one does

If we keep scrolling down, we'll also see:

  • a list of environment variables which affect how ls works
  • a description of the exit code(s) that ls might return, and under what conditions they might be returned
  • examples of how to use the command
  • various other bits of information which aren't immediately relevant to us

I recommend running man ls in your terminal, and skimming the results in order to get familiar with the typical format of a man page.

Searching a man page for a string

You may have seen the command ls -la in use by other devs, in a tutorial, etc. Let's assume you aren't yet familiar with the -la flags (note that this syntax indicates we're passing two separate flags, and is equivalent to -l -a). How can we get more information on these flags?

If we pull up the man entry for ls, we see it's quite long and includes documentation on many different flags. But that doesn't mean we have to read through these docs manually. We can search for a specific string, by using the / character. If we type /-l, we're taken to the first occurrence of the -l string:

-@      Display extended attribute keys and sizes in long (-l) output.

If this occurrence doesn't look like what we want, we can type the n key (i.e. lower-case "n") and move to the next occurrence:

-D format
  When printing in the long (-l) format, use format to format the date and time output...

If we do this enough times, eventually we arrive at this entry:

-l      (The lowercase letter “ell”.) List files in the long format, as described in the The Long Format subsection below.

If you accidentally skip past the occurrence you want, you can type N (capital "n") to go back one entry.

There are many more commands that you can use when searching a man page for a string, as well as many more commands to use in general. To see an exhaustive list, type h while inside a man page.

Builtin vs. External Commands

Depending on the command you give it, sometimes man will give you documentation on that command (like it did with ls). Other times, it returns an explanation of what a builtin command is in UNIX.

For example, let's try looking up the set command in its man page. I type man set into my terminal and I see the following:

BUILTIN(1)                                                        General Commands Manual                                                       BUILTIN(1)

       builtin, !, %, ., :, @, [, {, }, alias, alloc, bg, bind, bindkey, break, breaksw, builtins, case, cd, chdir, command, complete, continue, default,
       dirs, do, done, echo, echotc, elif, else, end, endif, endsw, esac, eval, exec, exit, export, false, fc, fg, filetest, fi, for, foreach, getopts,
       glob, goto, hash, hashstat, history, hup, if, jobid, jobs, kill, limit, local, log, login, logout, ls-F, nice, nohup, notify, onintr, popd, printenv,
       printf, pushd, pwd, read, readonly, rehash, repeat, return, sched, set, setenv, settc, setty, setvar, shift, source, stop, suspend, switch, telltc,
       test, then, time, times, trap, true, type, ulimit, umask, unalias, uncomplete, unhash, unlimit, unset, unsetenv, until, wait, where, which, while –
       shell built-in commands
       See the built-in command description in the appropriate shell manual page.
       Shell builtin commands are commands that can be executed within the running shell's process.  Note that, in the case of csh(1) builtin commands, the
       command is executed in a subshell if it occurs as any component of a pipeline except the last.
       If a command specified to the shell contains a slash ‘/’, the shell will not execute a builtin command, even if the last component of the specified
       command matches the name of a builtin command.  Thus, while specifying “echo” causes a builtin command to be executed under shells that support the
       echo builtin command, specifying “/bin/echo” or “./echo” does not.

This man page looks a bit different. It doesn't mention the command name (set) in the top-left corner, the way the man ls results did. Instead we just see the word BUILTIN.

So when does it give you one result, vs. the other?

As it turns out, man pages are provided only for "external commands", i.e. commands which come from UNIX. But the shell is not UNIX. UNIX is the operating system, and the shell is the application we're using to interact with the operating system. In fact, the reason why it's called the "shell" is that it surrounds the operating system, like an eggshell.

The set command is a builtin program provided by the shell, not an external command provided by UNIX. It's for this reason that shell authors keep the docs for their commands separate from the docs for external commands. The filesystem can be a messy place, and it's important to maintain strict compartmentalization for the sake of keeping things organized. As the British say, "everything in its right place".

How to tell if a command is a builtin

A quick an easy way to tell whether a command is a builtin command, external command, or something else is by using the type command. If we run type set in Zsh, we see:

$ type set
  set is a shell builtin

And if we type type ls, we see:

$ type ls
ls is /bin/ls

Lastly, let's define a shell function named foo, and run type foo:

$ foo() {
  function> echo 'Hello world'
  function> }
$ type foo
  foo is a shell function

Based on the response from type (command), we can tell ahead of time whether we should look up the command's docs using man or help.

Photo Attribution

Title: Unknown

Description: n/a

Author: No author specified.

Source: PxHere

License: Public Domain (CC0 1.0 DEED CC0 1.0 Universal)