OnCallReady

Lesson 1.9 · First Login · 19 min read

Asking the box: type, which, man, --help

In plain words

Imagine you have a toolbox where some tools are painted with a nickname, some are built into your own hands, and some are real tools in drawers. When you say "hammer", you want to know which one you get. type answers that: nickname (alias), built into your hands (builtin), or which drawer (/usr/bin/...). The drawers are searched in the order written on a list, $PATH.

Every real tool also has a sticker on it (--help) and a full manual on a shelf (man). Tools built into your hands have their own little manual, help. So instead of guessing, you ask the box in front of you, which knows exactly which version you have.

You are on a server with no browser, and you need the flag that sorts ls by size. Or a command works when you type it but not inside a script. The answer to both is on the box itself: it can tell you what a word means, where the program lives, and what every flag does - for the exact version installed.

What you need to know already: 1.7 Driving the shell (pipes, $?, grep).

The box documents itself

You will not remember every flag. Nobody does. What you need is the reflex of asking the machine in front of you instead of the internet's average of every version ever released.

Variables, briefly

The shell keeps named values called variables. You read one by putting $ in front of its name, and the shell swaps in the value before running the command:

$ echo $HOME
/home/learner
$ echo $USER
learner

Some variables are handed to every program the shell starts - these are environment variables (HOME, USER, PATH...). $? from lesson 1.7 is a special one the shell sets itself.

What is this word? type

When you type a command name, bash can find it in four kinds of place. It checks them in this order:

  1. an alias - a shortcut name that expands to a longer command (ll means ls -alF);
  2. a function - a small named set of commands defined inside the shell;
  3. a builtin - a command built into bash itself (cd, echo);
  4. a file - a program stored on disk, found by searching the PATH (below).

type tells you which one wins:

$ type cd ls ll grep
cd is a shell builtin
ls is aliased to `ls --color=auto'
ll is aliased to `ls -alF'
grep is aliased to `grep --color=auto'
$ type -a ls
ls is aliased to `ls --color=auto'
ls is /usr/bin/ls
ls is /bin/ls

-a (all) lists every match, not just the winner. ls shows up twice as a file because /bin is a symlink to /usr/bin on a modern Ubuntu, and both are on the PATH - same file, two routes to it.

This matters more than it looks:

Where is it? which and command -v

$ which ls bash
/usr/bin/ls
/usr/bin/bash
$ which tree
$ echo $?
1
$ command -v jq || echo "not installed"
not installed

which searches the PATH and prints the first match (nothing, and exit 1, if there is none). command -v is bash's builtin version: it also knows about aliases and functions, and it is the reliable way for a script to ask "is this installed?".

$PATH is just a list of directories, separated by colons, that the shell searches in order when you type a command name:

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

A program in the current directory is not found unless you say ./prog. That is deliberate: otherwise anyone who could put a file called ls in /tmp would take over your account the moment you cd /tmp and typed ls.

Command not found

$ tree
Command 'tree' not found, but can be installed with:
sudo apt install tree

Ubuntu has a helper that knows which package (an installable bundle of software - lesson 1.11) provides which command, and tells you. The exit status is

  1. On a stripped-down system without that helper you get the bare

bash: tree: command not found.

--help: the fast answer

Almost every program prints a summary of its flags with --help:

$ ls --help | head -5                 the usage line and the first options
$ ls --help | grep -- -S
  -S                        Sort by file size, largest first.

Piping into grep narrows a long help text to the line you care about. The -- in grep -- -S means "end of options": without it grep would treat -S as one of its own flags. Remember it whenever you search for something starting with a dash.

man: the full answer

man opens a command's manual page:

man ls
man 5 crontab        section 5: the format of the crontab file (a schedule of
                     recurring jobs), not the crontab command
man -k journal       search every page's one-line description (same as apropos)

(The journal is where Linux keeps its system logs; chapter 2 reads it.)

A man page opens in the pager - a program (less) that shows long text one screen at a time. The keys:

Space / b     page down / page up
/pattern      search forward, n = next match, N = previous
g / G         top / bottom
q             quit

Manual pages are grouped in numbered sections: 1 commands, 5 file formats, 8 admin commands. Every page has the same layout: NAME, SYNOPSIS, DESCRIPTION, OPTIONS, EXAMPLES, SEE ALSO. Read SYNOPSIS first - [ ] means optional, ... means "can repeat".

help: for builtins

Builtins have no man page of their own (man cd drops you in the giant bash page). Use bash's help:

help cd
help test
help set

In this simulator, plain help also lists the game commands.

The habit

Before copying a command from anywhere: type it, --help it, and look up the one flag you do not recognise. It takes ten seconds, and it is how you stop running things you do not understand as root.

What you can now do

Why it helps

The internet answers for every version ever released; the box answers for this one. Flags differ between Linux and macOS, between distributions and between releases. Checking --help or man on the actual machine prevents running a command that silently means something else there.

type explains a whole class of "works in my terminal, fails in the script or under sudo" problems: the thing you ran was an alias from ~/.bashrc, and scripts never load it. command -v is how a script checks that a tool exists before using it. And exit 127 plus Ubuntu's "can be installed with" hint tells you which package to install.

Commands in this lesson

echo type which command tree ls

FAQ

Should I use which or command -v?

In scripts, command -v. It is built into the shell, it knows about aliases, functions and builtins, and it returns a clean exit status (0 found, 1 not). which is a separate program that only searches $PATH, and its behaviour varies between systems. Interactively, type -a name is the most informative: it shows every match in the order bash would try them.

Why does man cd not show the cd page?

cd is a bash builtin, not a program, so it has no manual page of its own. man cd either fails or lands you in the huge bash manual. Use help cd, which prints bash's own short documentation for its builtins. help alone lists all of them. Others you will look up this way: help test, help set, help read.

What are the numbers in man 5 crontab?

Manual sections. 1 is user commands, 5 is file formats and settings files, 8 is administrator commands, 7 is overviews (man 7 signal). Some names exist in several sections: crontab(1) is the command, crontab(5) describes the file it edits. man -k word (same as apropos) searches descriptions across all sections, and man -f name lists which sections have that name.

Why is . not in PATH?

So that typing a command name never runs a file from the current directory by accident. If . were first in PATH, anyone who could put a program called ls in /tmp or a shared directory would run their code as you, or as root, the next time you cd there and type ls. That is why you type ./script.sh: a path with a slash skips the PATH search entirely.

My alias works in the terminal but not in a script. Why?

Aliases are defined in ~/.bashrc, which bash reads only when it starts for you to type into, and bash does not expand aliases in scripts even if they are defined. Scripts, sudo cmd and ssh host 'cmd' all run without them. That is by design: a script should not depend on one person's settings. Write the full command in the script instead.

In an interview Junior

How does the shell decide what to run when you type a command name?

It checks four kinds of place, in order:

  1. an alias - a shortcut from ~/.bashrc, like ll for ls -alF;
  2. a function defined in the shell;
  3. a builtin - part of bash itself, like cd and echo;
  4. a file - a program found by searching the directories in $PATH, left to right.

type tells you which one wins, and type -a lists every match: ls at your prompt is an alias for ls --color=auto, and the file behind it is /usr/bin/ls. If the name contains a slash, like ./prog, there is no search: that file runs. The current directory is not on the PATH on purpose. Two consequences: cd must be a builtin (a separate program could only change its own directory), and aliases exist only in interactive shells, so they vanish in scripts and under sudo.

Also asked: You need a flag you do not remember on a server with no internet. How do you find it? · What is the difference between which and command -v? · Why does a program in the current directory need ./ in front of it?

Practise this lesson in the terminal Free, in your browser - a real Ubuntu terminal to try it in, with missions that check your work.