The CLIP Companion
1: Introduction
This is a companion document to the CLIP Guidelines
If your utility does not belong to the CLIP family, then this
document does not apply to it, and you should consult the
general guidelines for picking an
appropriate family.
The purpose of this document is to provide guidance about "best practices" that should help
you prepare for UIRB and ARC reviews. This clarifies some details of
the CLIP guidelines and describes normal ways of solving common design
problems within the CLIP family.
As a "best practices" document, the information here is intended as
recommendations. This means that words like "must", "should", and "may" should be taken only in an advisory manner. An obvious exception to this is when the
actual CLIP guidelines are quoted, in the "Guidelines" sections, the words
there have the same force they have in the CLIP guidelines
This is an evolving document which will be updated to capture more
information as it is learned.
The glossary at the
end of this document defines terms used herein like "utility" and "operand".
Change Log
- 2006/2/2: Minor changes:
- Changed index.html to a version where expandable sections are expanded by default
- Changed "X Windows System" to "X Window System" (doh!)
- Made reference to man X11 as the best source of info about the X11 conventions
- 2006/2/16: Various changes based on ARC input
- Section about "families" extracted into a separate document to
serve as an entrypoint to companions for other families.
- Introduction section rewritten to make it clearer this only
applies to the CLIP family and that this is guidance to folks before an
ARC review, and not a way around the ARC process
- Slightly different wording about the case where hyphens or long
names are used in utility names and subcommands to better match how
this was expressed in the case for PSARC/1991/031.
- Put the "idioms" section into a section #5, rather than 4.7,
because it is in some ways qualitatively different than the other 4.x
sections which are about specific chunks of syntax.
- Added notes to point to specific guidelines when text in section 4 mentions things required by the guidelines.
- Changed "e.g. " to "e.g., "
- 2006/3/16: More changes
- Removed section 3.1, a repetition of the information extracted a month ago (not sure how that was overlooked)
- Added note in introduction emphasizing that this is "advisory" material.
- Tightened up some wording
2: Big Questions
Consider these questions when you start to design a utility:
- Are there other utilities which your users will think of as closely "related" yours? (That is, will your users use other utilities to manipulate the same things that your utility does?)
For example, if you are creating an X Window System utility, the people that use it will also use other X Window System utilities.
- Has your utility shipped before? (That is, is your utility part of an update, or may it have been used in a script?)
- If so, see the advice about "Backward Compatibility"
- Can you write or draw a diagram of the objects that your utility operates on?
For example, a "storage set" may have a set of disks, each of which may have a set of partitions
- If not, see the section about Object Models.
- Does your utility have multiple actions, or do you have options that specify actions?
For example: can your utility both create and un-create something, or do you have an option like "-a" to mean "add"?
- If so, see the guidance about subcommands.
- Does your utility operate on multiple kinds of objects?
For example, does it manipulate disks, storage sets and disk mirrors?
- If so, see the guidance about subcommands of the form "verb-objectClass"
- Does your utility allow the user to specify values which are attributes of an object (as opposed to values that affect an action the utility can perform)?
For example, do you specify the port number for a server (as opposed to getting a detailed listing of servers).
- If so, see the guidance about Properties
3: General Design Guidance for the CLIP Family
3.1: Backward Compatibility
Utilities are used in two ways:
- In an interactive environment where commands are issued and results are returned.
- In scripts
When used in a script, a utility is effectively a programming API. Changing its interface (if it has been specified as a stable interface) can cause programs (scripts) to stop working,
which, in turn, can cause a multi-million dollar facility to stop functioning.
As a result of this, you should be very cautious any time you change the interface to your utility.
FAQ
- Q: My utility has shipped, but is in family Foo. I'd like to make it follow the CLIP guidelines.
- A: This is a delicate situation that should be thought about carefully.
In some cases, advice from this document can be used to guide the design of an existing utility without breaking any existing use. It is up to your product team to decide whether this evolution of the interface brings enough value to be worth the change.
Note that a utility can't be moved in isolation from one family to another. All related utilities would need to be moved so as to maintain a consistent
experience for your users. Because this kind of movement from one family to another can be highly disruptive, it should be considered only in very rare circumstances.
- Q: I can't adhere to this standard without making incompatible changes. But, they're small. Isn't that OK?
- A: In the majority of the cases, this isn't OK. Causing scripts to break is very undesirable.
3.2: Overall Design
One of the most effective tools for designing a command line interface is to first figure out what "object model" the utility will expose
This usually means identifying the kinds of objects that the utility operates on and the relationships among those objects (e.g., some objects are contained in other objects).
Note: This doesn't mean the objects in the implementation of your utility (e.g., subclasses of java.lang.Object). It means the objects that the end user must think of.
For example, a hypothetical disk management utility might have these objects:
- Storage Set
- Disk
- Disk Mirror
- Tape Drive
An object model can be enhanced by noting the properties and operations that can be performed on each kind of object. This might make a full object model look like this:
| Object Kind |
Properties |
Creation Actions |
Addition Actions |
Change Actions |
Display Actions |
Other Actions |
| Storage Set |
Name, Location |
|
add(disk, mirror tape) |
|
|
power on, power off |
| Disk |
Model, Serial Number, Size |
|
|
format |
list, show |
|
| Disk Mirror |
Mirrored Disk, Model, Serial Number |
create mirror, delete mirror |
|
|
list, show |
|
| Tape Drive |
Contains Tape, Capacity |
|
|
erase |
list, show |
rewind, wind |
Once you have an object model like this, much of the rest of your command line interface design can follow very automatically.
Note that some utilities operate on an object model where the topmost object is always a singleton on a system.
In these cases, the subcommands operate on the objects contained by the singleton, and that singleton object does not need to be specified in a command (as such, these utilities generally take no operands).
If the object model is fairly complex, you may want to ask: "Should I create one utility or many?" There are no firm rules for this. In general, fewer utilities are better. At the same time, if the result is a utility with 50 subcommands, it may make more sense to have multiple utilities.
In general, the best rule of thumb is to look at how your users will think of the set of objects, and then have one utility for each set of objects that have related meanings to your users. When in doubt, it is better to have one utility than many separate utilities.
Another important tool for CLI design is to do a usability study of the utility. It is easy to create only the parser for your utility and run a study with that. In this way, you can try several variations of your interface and get feedback about which is best. Often, the results of a usability study are quite different from what your intuition would predict.
Another design factor to remember is that most of the time your users will not use your utility exclusively. Instead, they will often use it in conjunction with many other utilities. This is why adhering to the guidelines of your utility family is important, and why it isn't useful to optimize your interface to a high degree.
Remember that anything that the user can specify on the command line can show up in places like ps output. Because of this, no potentially sensitive information should be specified on the command line. For example, rather than specifying a password as an option argument, the password should either be asked for interactively or specified in a file which is named on the command line.
4: Design Guidance For CLIP Syntax
4.1: Commands
Guidance
The following command examples provide some context for the sections below.
$ qsformat -q -f ufs -p name="mything" foo
$ qsdisk eject --force -n mydisk
In the first of these, the utility named qsformat is given three options (-q, -f ufs and -p name="mything", where the third is specifying a property) and is operating on an operand named foo.
In the second, the utility named qsdisk is given a subcommand eject which is given two options (--force and -n) and is operating on an operand named mydisk.
FAQ
- Q: My utility has multiple usage lines (e.g.,
qsformat -abc and qsformat -jkl). Someone told me I should use subcommands. Why is that?
- A: Multiple synopsis lines suggests strongly that you actually have multiple different operations. Each operation is better presented with subcommands.
4.2: Utility names
Guidance
The name of a utility should uniquely identify the utility and give some reasonable hint as to what it does. As a designer, you should strive to find a balance between clarity (e.g., sun-penta-processor-performance-tuner) ease of typing (e.g., sp), and memorability.
Note that
utility
names and subcommands longer than 9 characters or with hyphens deviate
from the CLIP guidelines (guidelines 1, 2 and 14). These deviations are
usually acceptable when they encourage clarity and do not hinder
frequent use. Any deviation from the
guidelines should be specified in the case materials when you submit
your utilities to an architectural review committee.
One common strategy to try to meet these constraints is to rely on acronyms. This can be a reasonable strategy, but try to avoid using non-obvious acronyms (for an example of what not to do, what does sctpgtadm do?)
Sometimes, a set of related utilities share a common prefix to distinguish them from others. One example of this is Sun's clustering utilities use the prefix cl.
At the same time, avoid product names in the utility name, since product names change frequently. As one example of what not to do, the Sun Studio IDE is called sunstudio, which will be inappropriate as soon as the product name changes.
If your utility has no subcommands, it should have a verb-like name, and should follow the general guidelines in the subcommands section below.
If your utility has subcommands, give it a noun-like name. It is particularly good if the kind of object it operates on is in the utility name (e.g., qsdisk supports multiple operations on disks).
Guidelines
- Utility names should be between two and nine characters, inclusive.
- Utility names should include lower-case letters (the lower character classification) and digits only from the portable character set.
FAQ
- Q: My utility name is 20 characters long. Is this OK?
- A: It probably is not OK. While some users do use auto-completion features in shells, many don't. Your utility name doesn't need to be literal or complete. Perhaps you can replace several words of the name with something more generic, or do some careful abbreviation. If your utility name must be longer than the maximum in the guidelines, you should note this exception in the materials you present to any review bodies.
- Q: What about prefixes like "mk", "ls", "rm" as found in some *nix utilities?
- A: These conventions are found more in the getopt family. Additionally, these names partially conflict with the names that already exist in the CLIP family for the same operations.
List
- cfg
-
If your utility has no subcommands, and is used to do initial configuration of some object (usually, this configuration consists of setting values for various properties), then the suffix
cfg can be used. For example regioncfg might be a utility to do initial configuration of a "region". Use "cfg" rather than "config" because it is a well-recognized abbreviation and helps keep the utility name short.
- adm
-
If a utility performs various operations on several kinds of objects, then using a suffix of
adm is good. For example sarxadm might allow the user to administer a variety of objects within the "sarx" subsystem. Use "adm" rather than "admin" because it is well recognized and keeps the name short.
- mgr
-
If a utility performs many operations on a particular kind of object, and the only reasonable name for the utility is that kind of object and that name is too generic, then use the suffix of "mgr". For example, imagine that there is a kind of thing in the system called a "part", and it seems reasonable to have commands like
part create etc. That name, "part" is probably too generic. So, use the name partmgr instead.
4.3: Subcommands
Guidance
A subcommand is used to name the operation that a command should carry out. For example:
sharemgr create foo
The subcommand here is "create" and it tells sharemgr to create something named "foo".
Subcommands provide a way for users to easily remember the operations a utility can perform. Each subcommand also has its own set of options, which simplifies remembering which ones are related to a particular operation.
Like utility names, subcommand names must find a balance between clarity, ease of typing, and memorability. Similarly, it is good to avoid acronyms and other abbreviations that aren't obvious. Unlike utility names, there is no "tab completion" for subcommands, so it is very important to consider how frequently a subcommand must be typed.
Subcommand names should be verbs that describe the action to be performed. Single word subcommands are best. For example:
qsdisk format adisk
qsdisk eject adisk
qsdisk verify adisk
In some cases, a utility may operate on a type of object and its sub-objects. In these cases, the subcommand should be a verb followed by a hyphen followed by the name of the kind of object to operate on. For example:
qsset create myset
qsset add-drive -q newdrive myset
qsset remove-drive -q newdrive myset
qsset delete myset
As mentioned above,
some of these forms deviate from the CLIP guidelines. This is usually
acceptable. You should mention these deviations in your case
materials.
As an aside, note that one effect of the naming recommendations for utilities, subcommands and so on is that the command becomes vaguely "readable" as an English sentence.
Guidelines
- The form utility-name subcommand [options] [operands] is appropriate for grouping similar operations.
Subcommand names should follow the same conventions as command names as specified in guidelines 1 and 2.
- The subcommand in the form described in guideline 14 is generally required. In the case where it is omitted, the command shall take no operands and only options which are defined to stop further argument processing when encountered are allowed. Invoking a command of this form without a subcommand and no arguments is an error.
FAQ
- Q: Why should I use subcommands, rather than a set of separate utilities without subcommands?
- A: Both approaches are reasonable. Using subcommands is beneficial because the user only needs to remember one name explicitly (the utility name). The man page or --help output also makes it easy to discover all the related functionality in one place. Another factor to consider, however, is frequency of use. If your utility will be used very frequently, then it may make more sense to represent it as a set of utilities.
- Q: Why should I use subcommands, rather than options? (e.g.,
qsdisk create -q mydisk versus qsdisk -c -q mydisk)
- A: In the CLIP family, subcommands are preferred over using options because we believe they make it easier to remember and discover functionality.
- Q: My utility has XX subcommands! This seems terrible for our users!
- A: If you have XX subcommands, then you have XX operations. Unless you do a deep redesign of your utility, you will have the same number of operations no matter what you do.
In our experience, designing with subcommands still provides an easier way to manage large numbers of operations than other approaches.
- Q: I'd prefer to see verbNoun, verbnoun, "verb noun", "verb -t noun" or "noun" as my subcommand form, rather than "verb-noun"
- A: This is one of these cases where all the possible design alternatives provide roughly the same level of usability.
The design question then becomes: what is most consistent?
Each of these design possibilities has been closely examined, and the "verb-noun" scheme seems to be the best. "verbNoun" involves mixed capitalization which many dislike. "verbnoun" tends to produce names that are hard to parse when unusual terms appear in them. "verb noun" and "verb -t noun" don't really save any typing and add other complexities. Finally, "noun" doesn't convey any sense of action.
- Q: I seem to need to specify more than one level of objects (e.g., verb-noun-subnoun). What do I do?
- A: Usually, this suggests that your object model is too complex, or your decomposition into utilities isn't as fine grained as it should be.
Try a different design. It is true that in programming languages like, say, Java, you can say things like myObject.getFoo().getBar.getBaz().doSomething(), and this kind of nesting is natural for a developer.
Our usability data suggests, however, that administrators are less eager to think in terms of deep hierarchies like this.
- Q: My subcommand allows two very different uses, and each has mutually unrelated options (e.g.,
myutility add [-gou] entity and myutility add [-ghklr] entity
- A: You should revise your design. This suggests that you actually have two different operations, and so should use different names.
- Q: Can I allow my subcommands to be truncated? (e.g., type
qsdisk cr for qsdisk create)
- A: You may not. This limits future compatibility and thus may break scripts. See the options section, below, for more thoughts on this topic.
- Q: Is my subcommand limited to 9 characters like a utility name is?
- A: Like the utility name, you should strive to meet the requirements.
- Q: I have a subcommand called "print". Some people tell me that isn't good. Is this true?
- A: If your print subcommand will direct information to a printer, then it is probably a good name (though, it does demand that you explain why people shouldn't use the standard printing utilities instead). If your goal is to display information on the screen, a name like "show" or "list" or some other would be better and avoid the possible confusion of people thinking you mean to direct information to a printer.
- Q: I'd like to have a "help" subcommand.
- A: We'd rather not see this, since the "--help" is already available and you must support that. We want users to become familiar with using --help since it can be used with all CLIP utilities (whether or not they have subcommands). Providing other ways to get help simply makes our overall set of utilities seem inconsistent.
- Q: My utility mostly uses subcommands, but I'd like to allow one case where specifying no subcommand means to do something special. Is this OK?
- A: No. If that subcommand takes any operands, those operands may conflict with some future (or present) subcommand and that can cause scripts to break.
List
- create
- Creates a new object.
- delete
- Un-creates a new object.
- add
- Adds an existing object to some set.
- remove
- Removes an existing object from some set.
- list
- Gets a list of objects
- show
- Displays details about an object
- set
- Creates or modifies properties on an object.
- get
- Displays properties of an object.
- unset
- Deletes properties of an object.
- reset
- Sets properties of an object back to their default values.
4.4: Options
Guidance
An option is used to change how an operation is carried out. The classic example is that ls displays a listing of the current directory, while ls -l displays a detailed (long) listing of the current directory. The same basic operation is done in both cases, but the option (-l) changes how that is done.
Options are somewhat complex, syntactically. Here are the general forms that are allowed:
-l : Short (single letter) option that takes no option-argument.
-l -a : Two short options that take no option-arguments.
-la : An alternate way of specifying the previous example, with the short options clustered
-f myfile : A short option with an option-argument (these may not be clustered)
--long-listing : Long option with no option-argument
--input-file=myfile : An alternate way of specifying the previous
CLIP guideline 18 requires that whenever there is a long option, there
must also be
a short option.
Options always appear after the utility name (if there are no
subcommands) or the subcommand and before the operands (guideline 14).
The set of
options may always be ended with a -- argument (guideline
11), and
everything afterwards is treated as an operand.
Guidelines
- Each option name should be a single alphanumeric character (the alnum character classification) from the portable character set. The -W (capital-W) option shall be reserved for vendor options.
Multi-digit options should not be allowed.
- All options should be preceded by the '-' delimiter character.
- Options without option-arguments should be accepted when grouped behind one '-' delimiter.
- Each option and option-argument should be a separate argument.
- Option-arguments should not be optional.
- When multiple option-arguments are specified to follow a single option, they should be presented as a single argument, using commas within that argument or blanks within that argument to separate them.
- All options should precede operands on the command line.
- The argument -- should be accepted as a delimiter indicating the end of options. Any following arguments should be treated as operands, even if they begin with the '-' character. The -- argument should not be used as an option or as an operand.
- The order of different options relative to one another should not matter, unless the options are documented as mutually exclusive and such an option is documented to override any incompatible options preceding it. If an option that has option-arguments is repeated, the option and option-argument combinations should be interpreted in the order specified on the command line.
- Long-options should be preceded by -- and should include only alphanumeric characters and hyphens from the portable character set. Option names are typically one to three words long, with hyphens to separate words.
- "--name=argument" should be used to specify an option-argument for a long-option. The form "--name argument" should also be accepted
- All utilities should support two standard long-options: "--version" (with the short-option synonym "-V") and "--help" (with the short-option synonym "-?").
- Every short-option should have exactly one corresponding long-option and every long-option should have exactly one corresponding short-option.
- The short-option name should get its name from the long-option name according to these rules:
- Use the first letter of the long-option name for the short-option name.
- If the first letter conflicts with other short-option names, choose a prominent consonant.
- If the first letter and the prominent consonant conflict with other short-option names, choose a prominent vowel.
- If none of the letters of the long-option name are usable, select an arbitrary character.
- If a long-option name consists of a single character, it must use the same character as the short-option name.
FAQ
- Q: I'd like to have options before my subcommands. This makes sense because some options apply to all operations.
- A: This often makes sense from an engineering perspective, but our usability data says most users don't understand the system model well enough to be able to predict whether the option should go before or after the subcommand.
- Q: I don't like the double dash on long option names, but I want to have long names anyway. Can't I use a single dash?
- A: No. This conflicts with the ability to cluster single letter options. Even if you can support both simultaneously at the moment, your utility may eventually require some of those letters for short option names.
- Q: I am running out of short option names. What do I do?
- A: First, check several details of your design. If you are using subcommands, note that you do not need to keep your option names unique across subcommands. That is, if you use
-f in one subcommand to mean "force", you can use -f in another subcommand to mean "file". Users are not bothered by this level of "inconsistency" (however, if you use -f to mean force in one subcommand, and -r to mean "force" in another, your users are likely to be unhappy).
If this doesn't account for your problem, review the section on "properties" below. Perhaps you are trying to do something with options that would be better with properties.
If you still have a problem, you may need to redesign your utility. You should discuss this with your UI designers or your review bodies to determine if this is reasonable for your utility.
- Q: I am finding it difficult to choose reasonable option names. For example, I have to say something like
-t (or, worse, -q) for "hostname". What do I do?
- A: Users appreciate mnemonic option letters, but this isn't an absolute requirement. Try to use the guidance in guideline 19 (above) to pick a better letter. If that doesn't work, consider using non-mnemonic letters (e.g.,
-q for "hostname"). Alternately consider redesigning your utility.
- Q: Can I allow truncation of option names (e.g., allow a user to specify
--input-file with --inp?
- A: This is not permitted. The reason is that a system administrator may use that abbreviation in a script, and the next release of your utility might contain an option like
--input-port. In that case, the abbreviation would now be ambiguous and the script would have to fail. This might be reasonable to do if you could force people to not use truncation in scripts, but this isn't something that can be done. Rather than have a multi-million dollar server go down because of something like this, abbreviations are not allowed.
- Q: Can I do something like
-f file1 file2 file3? (pass many values to a single option)
- A: Not in this way. That would be interpreted by your utility as
identical to
-f file1 -- file2 file3. To specify multiple
values for an option, you should separate them with commas (e.g., -f
file1,file2,file3) or spaces (e.g., -f "file1 file2 file3"),
or allow the option to be repeated (e.g., -f file1 -f
file2 -f file3)
- Q: Guideline 8 (above) says use commas or spaces. Which is better?
- A: In general, commas are better. There is a function,
getsubopt(3C), which can help parse these, and spaces can sometimes be a nuisance for users because of quoting requirements. However, there are times where it is necessary to use spaces (for instance,if your option accepts numeric values that may have decimal points, then you can't use commas because in some locales a comma is used as a decimal point separator). If it can be done unambiguously, it is reasonable to accept both commas and spaces. If all of this gives you a headache, consider simply allowing your option to be repeated and accumulating values with each repetition rather than replacing the earlier uses.
- Q: Can I have a
-h option to get help?
- A: See the discussion of "help" as a subcommand in the subcommands section.
4.5: Properties
Guidance
Sometimes a command is used to change or retrieve the values of object attributes. This is different than changing how an operation is to be carried out. For example, you might specify how a format operation should be done (quickly or thoroughly) as opposed to specifying that the label on a disk should be set to "fred" or "mydisk". The former changes an action, the latter changes an object.
It is possible to use options for both cases. But, some utilities use properties to specify changing values on an object, and options for changing how an operation is performed. Properties are specified with a name=value format. For example:
$ qsdisk format --quick-format newdisk
$ qsdisk set -p label="mydisk" newdisk
Note that properties are always treated as option-arguments to a -p or --properties option.
There are several variations of how properties are dealt with in different utilities:
- An object may have a specific set of properties that are "pre-defined" and a user can only change which values are stored in those properties.
- An object may have arbitrary properties added to and removed from it
- An object may allow specific properties to be added to and removed from it.
See the section about idioms, below, for details about the set, get etc. subcommands.
Note that there is one problem with using properties. Some shells can be started (e.g., with the -k option to sh) so that any command that has strings of the form name=value will be consumed by the shell. As a result, the utility will never see them. That is, in the rare case when a shell is started in this mode, any utility that uses properties (including things like mkfs) will not work correctly.
FAQ
- Q: How should I specify property names? Should they be "propertyname" or "property-name" or "propertyName"?
- A: The form "property-name" (all lower case, with hyphens separating words) seems to be the best. But please talk to us if you have a good reason they should be different.
- Q: I think I need to use hierarchical property names. Is that OK?
- A: We've seen at least one case where this is reasonable. Please talk to us and explain your need.
- Q: I can't tell if I have a property or an option. I can think of doing it either way.
- A: If you can retrieve the value later from the object affected by the operation, then it is a property.
- Q: My implementation doesn't have the notion of properties. The interface to the utility shouldn't have these.
- A: It isn't necessary that the interface reflect the implementation. If your users are likely to naturally think of these values as properties, then that
is how they should appear in the interface, regardless of the
implementation
4.6: Operands
Guidance
Operands usually name the objects or things that your utility will operate on. These are listed after the options. There is little that can be said about how operands should be specified, in general, because these tend to be the most utility-specific part of the interface.
Guidelines
- The argument -- should be accepted as a delimiter indicating the end of options. Any following arguments should be treated as operands, even if they begin with the '-' character. The -- argument should not be used as an option or as an operand.
- The order of operands may matter and position-related interpretations should be determined on a utility-specific basis.
- For utilities that use operands to represent files to be opened for either reading or writing, the '-' operand should be used only to mean standard input (or standard output when it is clear from context that an output file is being specified).
FAQ
- Q: My subcommand can take multiple operands. Should I allow that, or just accept one?
- A: If your users can specify multiple operands as easily as they can specify one, then it is good to allow multiple. However, two design considerations should be made here.
First, if you must add some kind of special syntax to disambiguate between one and multiple, then you should allow only one.
If your common use case is to allow multiple, then you should allow multiple. (sometimes those two criteria will conflict, and so you must make a difficult design decision).
Second, If most of your subcommands can only operate on one operand, but you have one subcommand that can operate on many, you may want to still restrict the latter to operate on one, so that your utility seems more consistent to your users.
- Q: What happens if the user specified three operands, and the utility fails when processing the third?
- A: The general Unix convention is to continue with processing the third and report an error (both a message and a status code) when all are done.
- Q: I'd like to specify things with operands in a particular order. Rather than using required options, I'd like to say that operand #1 is one thing, operand #2 is another thing, and so on.
- A: These are called "positional parameters". In general, these seem to be a bad idea. More than two positional parameters is hard for people to remember. In the general case, even two is difficult because it is often hard to remember whether A goes before or after B. One common utility which uses positional parameters reasonably easily is
cp, where the last operand is the destination while the
preceding are all the things to be moved. Yet, you have probably on occasion not specified the destination item and so moved all the files into some other location than you intended. This demonstrates that this good case can still cause problems. In general, we strongly recommend the use of options (even required options) rather than positionally-significant operands because this reduces the usability problems that positional ones involve.
5: Idioms
This section discusses a few interface patterns that are used across many utilities.
5.1: Set/Get/Unset/Reset/Create
It is common to want to specify properties that are applied to objects. This is a common idiom for supporting this in a command line interface:
myutility create -p propname=value newobject
myutility set -p propname=value newobject
myutility get -p propname newobject
myutility unset -p propname newobject
myutility reset -p propname newobject
In this idiom:
set is used to assign an initial or new value to a property (and possibly create the property in the object).
get retrieves the value from the object. If one property name is specified, then only the value is returned. If multiple property names are specified, then multiple "name=value" pairs are returned. If no property names are specified, then all properties are returned in "name=value" pairs.
create can be used both to create an object and as an implicit set operation.
unset removes the property and its value from the object (only relevant if you can add a property to an object)
reset sets the value of a property to its default value (only relevant if properties are pre-defined in the object)
In some cases, the -p is redundant. Nonetheless, it should always be used with these subcommands. Even in those cases users do not particularly mind typing these letters, and prefer them to be there so they can behave in predictable ways across utilities. In these cases, however, it may be made optional if there is no chance that it will ever become ambiguous.
If the object model has subobjects that have properties, then the subcommand names should be of the form setprops-objecttype.
5.2: List, Show and Get
list and show have different meanings, and usability studies reflect that most users guess the purposes accurately. list is used to get a list of objects. This may be a plain list of their names, or their names with some additional information about each. show, on the other hand, displays detailed information about one or more objects.
In some cases, get and show are both used in the same utility. In this situation, get shows just the properties of an object, while show may show those properties plus additional information.
6: Design Guidance For Other Parts Of The Interface
6.1: Help
Usability studies have repeatedly shown us that man pages and --help output are crucial parts of the user's experience. Small terminology problems, inconsistent formatting, and similar issues can seriously hinder a user's ability to use a utility easily.
Use the standard formats for man pages and --help output as listed in the CLIP spec. In particular, note that each subcommand should be listed on a separate line in the synopsis section of the man page.
For utilities that operate on many different kinds of objects, it may be reasonable to group the subcommands in the help output by the kinds of objects they operate on. For example:
$ myutility --help
Usage: myutility <subcommand>
Use this utility to do something wonderful
ROOT-OBJECT SUBCOMMANDS
create Create a root-object
delete Delete a root-object
list List root-objects
SUBOBJECT SUBCOMMANDS
create-subobject Create a subobject
delete-subobject Delete a subobject
6.2: Output
When your utility writes information to standard out, keep in mind whether it may be used only by people, only by other utilities, or both.
In the most trivial of cases it may be possible to address both needs
in one format, but that's rarer than you might think. Human-oriented
output formats need to be localized and should optimize for
readability over formal consistency. As the format evolves, it should
evolve for readability even if that involves a significant structural
overhaul. On the other hand, program-oriented output formats need to
be optimized for precision and extensibility, usually at the expense
of readability.
Example: ls -l output
This format was developed before this dichotomy was understood, and it
has feet in both camps. In many ways it fails both.
If you think that ls -l output is parsable, have you considered the
effect of localization on date formats, or the effect of special
characters in file names? A file with " -> " in its name can cause
problems, as can a file with a newline in its name. Where would new
information be added into "ls -l" output that wouldn't break existing
consumers?
On the other hand, because there are machine consumers of ls -l output (despite its problems), it can't be cleaned up for human consumption either.
Output intended for humans should have a stability level below
"Unstable".
On the other hand, output intended for programs requires precision
(absolutely every possible special character and pathological case must
be handled unambiguously) and extensibility, so that next year's
output can contain more information but be usable with today's consumers.
Output intended for programs should have an appropriate stability
level, anywhere from Unstable to Stable.
When it comes to tabular data, here are some thoughts:
If your subsystem uses and produces relatively simple data that can
be expressed effectively in tabular form, then you should provide a
way for users to get or provide that data in a stable space- or
colon-delimited form for use within scripts.
If your subsystem uses or produces complex data that cannot be
expressed effectively in tabular form, consider providing a way to
get or provide this data in XML with appropriate stability for the
tags and schema.
If there are compatibility issues with third-party products or
controlling standards, then those should be weighed as well. XML
and tabular forms do not necessarily comprise all of the interchange
media of choice across all possible products.
6.3: Other Important Topics
There are many other things relevant to the command line experience that are not covered here currently. This is a list of things that may be addressed in the future
- Where a utility (and its support materials) should be placed in the filesystem (for the moment, refer to
man -s 5 filesystem
- Non-batch-oriented interfaces
- Subshell interfaces (libtecla)
- Error Messages
- How to manage lists of objects in the object model
- perhaps add-foo, remove-foo, set-foo-list
- Error codes
- More guidance about help and man page issues
- Conventions for using standard in and standard out
- Alternate of subcommands
- When should/may subcommands and option names be plural versus when not?
- possible: when a subcommand always or primarily operates on a set, use a plural. otherwise use a singular
6: Terminology
This document uses a particular set of terms to refer to parts of the command line experience:
- Utility
- A program, excluding special built-in utilities provided as part of the Shell Command Language, that can be called by name from a shell to perform a specific task, or related set of tasks. Sometimes called a "command"
- Subcommand
- An argument to a command used to specify which operation the utility should perform.
- Option
- An argument to a command that is generally used to specify changes in the utility's default behavior. Sometimes called a "flag" or a "switch".
- Option Argument
- A parameter that follows certain options.
- Operand
- An argument to a command that is generally used as an object supplying information to a utility necessary to complete its processing. Operands generally follow the options in a command line.
- Command
- A directive to the shell to perform a particular task.