This approach to parsing command lines also lends itself well to providing command completion and interactive help.
Going from what we already have – the POSIX standard and different approaches to Unix-like command-line interfaces in the wild – the first question that needs to be answered for a systematic approach is what design approach to choose for task-specific tool sets.
It seems that, historically, the phenomenon of task-specific tool sets did not (explicitly) exist on Unix and thus is a relatively new development in command-line utilities on Unix-like systems that is apparently rooted in the need for more powerful/complex tools to do more complex jobs well, such as package management or managing network interfaces. A general desire for a more orderly/structured tool box, where utilities for particular classes of tasks are arranged in some meaningful way, has probably played an equally important role here and is, in fact, intrinsically connected to managing increased complexity.
There are essentially three ways to implement task-specific tool sets:
A tool that needs to perform several distinct tasks, e.g., installing and removing software packages could simply utilize command-line options to denote the respective operation (“sub-command”). Doing that would, however, require dividing its options into three distinct categories:
Example: pacman
capital letters for operations
Implementing sub-commands as options is arguably not a good approach because it obviously doesn't honor the distinction between commands, which provide a set operation, and options, which are meant to merely alter aspects of that operation.
Not keeping sub-commands and options strictly separate also creates a user interface that is potentially harder to use because options cannot be given in random order anymore if some options denote commands that then have command-specific options. One way to partly mitigate this would be to at least allow global options to occur among command-specific ones. E.g., if a tool had the option `-v` for verbose output, then
<command> -v <option denoting operation>
<operation-specific options> and<command> <option denoting operation>
<operation-specific options> -v
should yield the same result, i.e., the meaning of -v should be
exactly the same in both cases: Generally be verbose. This would also be
advisable for the approach of using actual sub-commands. Non-hierarchical
command sets need to have that ability per se, if there are any global options.
One example of this design approach is OpenBSD's tool set for package management. It consists of a collection of four independent utilities (i.e., independent from the user's perspective):
pkg_addpkg_checkpkg_deletepkg_infoThere are two prevalent naming schemes for such command sets:
<toolset_prefix>_<command_name><toolset_prefix>-<command_name>toolset_prefix. But that would effectively mean creating a
manual page for a command that doesn't exist, like, e.g., git(1). (There's
no pkg(1) on OpenBSD, by the way.) So, this doesn't seem like an elegant
solution, also because it probably wouldn't make sense to make such a
manual page a requirement.
<toolset_prefix>_<command_name>) is rather
inconvenient to type.
An example of the sub-command approach can be found in Alpine Linux's package
manager, apk. Contrary to OpenBSD's pkg_* command set, it
offers a set of sub-commands, such as add, del,
update, and upgrade that have to be entered as
arguments to the apk command, e.g., apk add nano to
install the Nano text editor.
man apk-add instead of man
apk add. (Non-hierarchical command sets don't have this problem.)
Plan 9 leverages the system's directory tree to implement sub-commands.
E.g., all sub-commands of git reside under
/bin/git and the shell allows multiple path components in a
command call, e.g., git/add *.
It's not POSIX-compliant.
Running sub-commands this way makes it impossible to place options inbetween a main command and a sub-command. However, if all sub-commands accept all global options – which they probably should because that's arguably part of what makes them global – this is not necessarily a problem. Then again, this means that once a global option has been defined, that option's name is taken and cannot be used to mean something else inside the scope of a sub-command, which is quite impractical.
--Last changed: 2026-05-12
Copyright © 2021, 2022, 2025, 2026 Michael Siegel
This work is made available under the terms of the Creative Commons Attribution-ShareAlike 4.0 International License (CC BY-SA 4.0).