A reason why Unix programs sometimes support '-?' for help

April 13, 2022

I recently read Clayton Craft's -h --help -help help --? -? ???? (via). In part of it, Craft mentions '--? / -?' as help options, and says about them:

???? I have no idea where these came from, but my guess is that they are migrants from the wild west Windows-land, where I assume the shell won't try to expand ? into anything. [...]

I think there's a different and far more Unixy explanation, and it's our friend getopt(3), and the Bourne shell getopts equivalent. Both getopt(3) and getopts return errors, such as unrecognized options, through what we could call in-band signalling, instead of using an additional return value (both C and normal Bourne shell don't handle multiple return values very easily). Classical getopt(3) normally returns the latest option character for you to parse; when it hits an option character you don't accept, it instead returns a special marker character. This marker character is '?'. Shell getopts follows the same approach (although in the shell case, you might match on any otherwise un-handled option character).

(GNU getopt_long() has its own conventions for this return value.)

As a result, Unix programs using getopt (or shell scripts using getopts) can't have '-?' as a valid command line option for anything meaningful, because there would be no way to tell a real '-?' apart from an error. As a consequence of this, it's almost always safe to run a program as 'program -?'; no matter how large and weird its collection of command line option letters is (ls is famous for using almost all of them, including '-h'), it won't be using '-?' and so running it that way is a generally safe way to get some sort of usage message (and an error).

Once people start running 'program -?' to get a usage message, programs themselves have an incentive to make '-?' print a longer help message, and perhaps to list it in getopt() or getopts as a valid option, so that people no longer get "invalid option -- '?'" messages or the like when they're doing it deliberately.

(Since getopt() itself generates the 'invalid option' message, people will still get this for genuinely invalid command line options; listing '?' as a valid option only affects whether you get the message for 'program -?'.)

This gives you the situation where some programs accept '-?' for help (and probably then accept '--?' because why not), and some sources of advice suggest running programs as 'program -?' to at least get a basic usage message to remind you and perhaps some help too.

PS: In normal Unix shells, there's no problem using '-?' as a command line argument even though '?' is a filename wildcard character. Normally, non-matching wildcard characters are passed through intact as argument characters. Tcsh behaves differently, but if you use tcsh as your shell that's up to you.

Comments on this page:

tried just for fun, it seems that ksh (OpenBSD' pdksh) expands -? too:

% touch -- -l
% ls -?
total 10922
By cks at 2022-04-14 09:09:31:

If you have a '-<character>' file then using '-?' as a command line will expand it, I think in any shell. But almost all of the time you don't have such a file in the current directory and so an unquoted '-?' is safe. I should have been explicit about that in my PS.

By mtk@acm.org at 2022-04-14 11:37:00:

hmm... its origin may be older than that. the command interface for tops-20 was based on the use of ESC for recognition (now TAB) and '?' to make the command parser tell you what it was expecting (now also part of TAB). i always thought it was a reference to that usage.

Written on 13 April 2022.
« Mangling your distribution version in your Apt sources for fun and profit
Building Firefox from source and Rust versions »

Page tools: View Source, View Normal, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Wed Apr 13 21:20:42 2022
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.