Why Shell Builtins Lack Proper Man Pages

command linefreebsdmanosx

All shell builtins share the same manual page:

BUILTIN(1)                BSD General Commands Manual               BUILTIN(1)

NAME
     builtin, !

etc.

Then there is a little text describing what shell builtins are, and then a list that
looks something like this:

  Command       External    csh(1)    sh(1)
       !             No          No        Yes
       %             No          Yes       No

But if we do man grep we get sections such as

  • Bugs
  • History
  • See also
  • Standards
  • Description

etc.

Don't shell builtins have their own history, description and arguments like -A or -r? Why isn't that provided in the manual pages and how would I learn to use them correctly and efficiently?

Best Answer

Because builtins are part of the shell. Any bugs or history they have are bugs and history of the shell itself. They are not independent commands and don't exist outside the shell they are built into.

The equivalent, for bash at least, is the help command. For example:

$ help while
while: while COMMANDS; do COMMANDS; done
    Execute commands as long as a test succeeds.

    Expand and execute COMMANDS as long as the final command in the
    `while' COMMANDS has an exit status of zero.

    Exit Status:
    Returns the status of the last command executed.

All bash builtins have help pages. Even help itself:

$ help help
help: help [-dms] [pattern ...]
    Display information about builtin commands.

    Displays brief summaries of builtin commands.  If PATTERN is
    specified, gives detailed help on all commands matching PATTERN,
    otherwise the list of help topics is printed.

    Options:
      -d    output short description for each topic
      -m    display usage in pseudo-manpage format
      -s    output only a short usage synopsis for each topic matching
        PATTERN

    Arguments:
      PATTERN   Pattern specifiying a help topic

    Exit Status:
    Returns success unless PATTERN is not found or an invalid option is given.

Inspired by @mikeserv's sed script, here's a little function that will print the relevant section of a man page using Perl. Add this line to your shell's initialization file (~/.bashrc for bash):

manperl(){ man "$1" | perl -00ne "print if /^\s*$2\b/"; }

Then, you run it by giving it a man page and the name of a section:

$ manperl bash while
       while list-1; do list-2; done
       until list-1; do list-2; done
              The while command continuously executes the list list-2 as long as the last command in the list list-1 returns an exit
              status of zero.  The until command is identical to the while command, except that the test is negated; list-2 is  exe‐
              cuted  as  long  as the last command in list-1 returns a non-zero exit status.  The exit status of the while and until
              commands is the exit status of the last command executed in list-2, or zero if none was executed.

$ manperl grep SYNOPSIS
SYNOPSIS
       grep [OPTIONS] PATTERN [FILE...]
       grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]

$ manperl rsync "-r"
       -r, --recursive
              This tells rsync to copy directories recursively.  See also --dirs (-d).
Related Question