240 comments

[ 5.9 ms ] story [ 275 ms ] thread
The list is probably ignoring

    man foo
    apropos foo
    Info foo
;-)

Fun aside, I think -h/--help is nowadays the most widespread and accepted version in Linux/Unix-Land. A good CLI argument parser accepts both variants.

I always default to “man foo”, because of the occasional tool that when presented with -h or --help creates a file with that name; even if there’s no manpage, “man foo” will never have any undesired side effects.

Nearly every tool does have a manpage (even a basic one) thanks to Debian’s manpage policy: “Each program, utility, and function should have an associated manual page included in the same package or a dependency.… If no manual page is available, this is considered as a bug and should be reported to the Debian Bug Tracking System.”

The rare times I encounter a command‐line tool that has no manpage, I’ll sometimes write one and contribute it upstream.

Of course some programs have a useless manpage that points to info. Thankfully that is pretty much limited to GNU tools which I’m lucky enough to not have to use very often.

There is the occasion where the manpage is useless compared to the help or the website docs. For example, the ironic 'man doxygen'.
Or the man page for OpenSSL's config, which actually has many of the options in the man pages for `req`, `x509`, and `ca`.
Hey, at least this doesn't create a file:

  shutdown -h
> Fun aside, I think -h/--help is nowadays the most widespread and accepted version in Linux/Unix-Land

The most notable exception (to me) among modern tooling is the `aws` cli, which parses help as a subcommand. And if you try `--help` it just gives you an `Unkown option` response.

I'm mildly amused by the need to reserve a little bit of brain-space for the ways to ask cli tooling for help

It would be easy for the authors of this tool to fix this behaviour. Checkout `git --help` vs `git help`, both versions work. That's just being nice to the user.
/?
/help
(comment deleted)
man $command
Can someone remind me what tool I use to convert markdown to man pages? Even better, anyone have a good way to embed a man page into my README?
Or "help command" in powershell world. But applies to powershell cmdlets/functions only.

Edit: I just checked on windows, man is actually alias for help in PowerShell :)

Watch out for bloggers: they tend to make stuff up.

There are no "Posix long options" and therefore a "Posix-compliant" argument parser will not handle them just fine.

Long options set off using two dashes were popularized by the GNU utilities.

POSIX describes a getopt C library function and a getopts utility command. Neither of them specify any requirements for long options. They will not parse long options "just fine"; not without extensions for it.

In the GNU C library (and compatibles), there is a getopt_long function that supports long options; there is no attempt made to extend the POSIX getopt to handle long options.

POSIX does not have a help option convention: -h is not consistently a help option. The "Utility Syntax Guidelines" makes numerous recommendations about options; no mention is made of anything resembling long options, or that if there is a help option, it should have such and such name.

I don't know of any utility for which POSIX requires some kind of help option; it describes only the man command.

I feel the same when they talk about UNIX, but are actually describing GNU/Linux.
GNU/Linux == GNU is not Unix (even) over Linux.

:)

I usually refer to these as "GNU-style arguments", whether or not that's the correct terminology. The fact that Go-based utilities tend to use the `-option` style (with a single hyphen) still bothers me.
And since the article is using podman as an example: podman does have a manpage. The actual standard way of getting documentation on utilities, man podman, works just fine.
I think man pages tend to be more heavyweight than people sometimes; if I just want to see a few of the most common options to copy, it's a lot easier to have a few lines just printed out rather than having to crawl through potentially dozens of pages being piped to `less` and then open a second terminal pane if I want to look at it while I'm typing my command.

Put another way, I think `--help` is basically the CLI equivalent of generated API docs, whereas manpages are like long-form prose documentation. While you can get by with just one of them, the experience is going to be worse for certain use cases, and generally for anything beyond a certain level of complexity, your users will be better off if you provide both.

Downvoted because You can correct the article without making it personal
This is overly pedantic. The point is that people using POSIX (i.e. Unix-like) systems expect -h or --help to work, as a matter of convention. What the letter of POSIX-the-standard says doesn't really matter to most people.
But it’s not overly pedantic. POSIX is literally a formal standard, and that standard does not provide a mechanism for long options. Other “POSIX (i.e. Unix‐like) systems” like the BSDs do not generally use long options, nor do they generally support -h as a “help” flag.

What you’re describing as a POSIX convention is really a GNU convention. But the world of POSIX consists of more than just GNU. So the grandparent post is correct.

POSIX is a legacy “formal standard”. The two biggest players by far of the Unix branch (Linux and MacOS) both implement it losely.

The POSIX strictness battle have been lost more than two decades ago. Behaving as if it did not, is overly pedantic.

A far more egregious error is pretending that -h/--help is some sort of universally implemented or agreed upon practice among command‐line tools.
Large, complex code written in C that has a wide API footprint will work with little or no modification among systems like GNU/Linux, Solaris and Mac OS.

The specification is online and people use it when coding, refer to it it in discussions and when filing bug reports.

2018 edition: https://pubs.opengroup.org/onlinepubs/9699919799.2018edition...

It's been my experience that the maintainers of major FOSS projects take it seriously when something is reported as being at odds with POSIX.

I don't remember any recent "POSIX strictness battle"; you didn't just make that up, did you?

There was as struggle starting in the 1980's to deal with incompatibilities among large numbers of vendor-specific derivatives of Unix that were cropping up everywhere. Unix brand incompatibilities negatively affected the users, who wanted their programs (and skills) to transfer. That is more ancient history. In retrospect, it looks like the standardization effort was broadly successful.

POSIX is not exactly standing still; it has been amassing new interfaces, and vendors adapt them as specified.

When I started coding in Unix, gethostbyname was the way to resolve DNS; now you have getaddrinfo, which is more generic and can give you IPv6 and IPv4 results in the same call. Even in basic Unix functionality, there are new features: for instance, various "at" functions, like openat: open a file relative to a specified directory descriptor, rather than the current working directory. POSIX specified threads that work everywhere, shared memory that works everywhere and other things.

There is rather a struggle between "use latest stuff in POSIX" versus "have code work on older systems".

But, overall, POSIX is a huge relief.

POSIX is a big reason why you can take code written using Glibc and get it running on Musl. Or on Cygwin.

An alternative C library that has Glibc compatibility as its goal would be a lot more difficult to develop if it had to be based entirely on reverse engineering Glibc. The Glibc documentation isn't complete enough. (And, doh, that's because it expects you to refer to POSIX for the details.)

https://www.freebsd.org/cgi/man.cgi?getopt_long(3)

> HISTORY

> The getopt_long() and getopt_long_only() functions first appeared in the GNU libiberty library. The first BSD implementation of getopt_long() appeared in NetBSD 1.5, the first BSD implementation of getopt_long_only() in OpenBSD 3.3. FreeBSD first included getopt_long() in FreeBSD 5.0, getopt_long_only() in FreeBSD 5.2.

So the parsing support is there. And it is used, e.g. tar aka bsdtar:

https://www.freebsd.org/cgi/man.cgi?tar(1)

So long options were popularized by GNU but have since become common across different POSIX operating systems.

> So the parsing support is there. And it is used, e.g. tar

Yes, the parsing support is there, so software written in the GNU style does build and run correctly on BSD systems. But although you bring up tar (a command that is well known for its unusual and unconventional flag handling), it is generally the case that commands on BSD operating systems do not use long options.

Representative examples of prominent 21st century BSD software that do not use long options:

mandoc: https://mandoc.bsd.lv/man/mandoc.1.html

jail: https://www.freebsd.org/cgi/man.cgi?jail(8)

zfs: https://www.freebsd.org/cgi/man.cgi?zfs(8)

acme-client: https://man.openbsd.org/acme-client.1

signify: https://man.openbsd.org/signify.1

doas: https://man.openbsd.org/doas.1

smtpd: https://man.openbsd.org/smtpd.8

And of course old classics like ssh: https://man.openbsd.org/ssh.1

kazinator’s point, that there is no POSIX convention of using -h for help, is correct. That convention came from GNU, and while the idea has spread due to GNU’s influence, there are other prominent schools of thought in the POSIX or Unix‐like ecosystem. I would certainly not agree that long options are the common case on BSD systems.

> ???? 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. Using these options will cause problems for anyone using common shells like bash, zsh, others. Don't do it.

They come from getopt() returning '?' for any unknown option, which usually ends up being the default case in your switch, but could be '?' to be explicit.

The bit about help as a subcommand and having to edit it out in a cumbersome way really hits home.

I'm looking at you, otherwise-excellent wp-cli. :-)

You need to discover either emacs or vim shortcuts for bash. I can't imagine living without `set -o vi`
At least in bash, just run

    ^help^^
Which will rerun the previous command but substitute "help" with "" (nothing).
It is in the nature of bash that you can go a decade without ever figuring something out only to have your life changed by a random comment on the internet.

So thank you. That changes everything!

:D I have been on the receiving end enough times that I am very very happy to have passed it on this time.
Is there a shortcut to reuse the result of the last command? “which java => ll $(!!)”, but the “!!” reexecutes the last command, I’d like something which doesn’t.
I'm not personally aware of a way to do that. When I need to do that I do indeed just run $(!!)
This is amazing! I don't think I'll use it for help (up-arrow, ctrl+w is fewer keystrokes), but I can think of many other situations where I want to substitute one word of a very long command and didn't realize it could be this easy
I think

  ^help^
does the same thing. The bash manual says ^string1^string2^ is equivalent to

  !!:s/string1/string2/
where / can be any delimiter, and the "final delimiter is optional if it is the last character of the event line." So, not so surprising that the third ^ is optional too.

TIL: In either of these forms, if string1 is empty, it is set to the last string1, or, "if no previous history substitutions took place, the last string in a !?string[?] search." E.g.

  $ echo foofoo
  foofoo
  $ ^foo^
  echo foo
  foo
  $ ^^bar
  echo bar
  bar
> is equivalent to

> !!:s/string1/string2/

I didn't know about this syntax either.

I thought I knew a bit of bash and it turns out I'm a novice after all this time. How fun.

The last point reminds me of the frustration of quitting the Python REPL.
I always forget the "version" switch. Is it '-v' or '--version' or '-version', everything's just a bit different and I can never remember what needs what to tell me its version.

[edited to add] As others have reminded me, there's also simply 'version'

I automatically assume `-v` is short for `--verbose` rather than `--version`, and always type out the latter.
I don't know but I always expect -V for verbose, and -v for version. However, I do acknowledge its not consistent :(
Everything uses --version, except `java -version`.

Except Java 17. Java 17 went to `java --version`. And `java -version` doesn’t work anymore (Yes I jumped from Java 8 to 17, but most people did).

And (e.g.) OpenSSL IS `openssl version`, with no dashes at all.
To be fair, when deciding how to implement CLI options, it's probably advisable to run as far away as you can from drawing any sort of inspiration from openssl. Even git looks like a paragon of UX compared to the openssl CLI.
You don't think that -text -noout is an intuitive way to output something as text?
mawk is the worst, which, given the article's claim about POSIX, is ironic, because mawk is POSIX-compliant.

  $ mawk --version
  mawk: not an option: --version
  $ mawk --help
  mawk: not an option: --help
  $ mawk -W version
  mawk 1.3.4 20200120
  Copyright 2008-2019,2020, Thomas E. Dickey
  Copyright 1991-1996,2014, Michael D. Brennan

  random-funcs:       srandom/random
  regex-funcs:        internal
  compiled limits:
  sprintf buffer      8192
  maximum-integer     2147483647
And mawk is (was in 16.04 at least) the default version of awk on Ubuntu. How is the user supposed to know this magic incantation? ¯\_(ツ)_/¯
To be fair, I can see this coming out of a strict reading of POSIX: it doesn’t say a single word about GNU-style long options (though there is an implied hole where they can fit), but explicitly leaves -W with an argument as a place for implementation-defined crufties when passed to Awk (I haven’t the slightest idea why).

(Honestly I’d rather not have the convention of programs themselves handling this at all and instead have this be `ident awk` or similar, but I understand this is not going to happen.)

I can only imagine that the "w" stands for "what the hell do I need to pass this thing to get it to tell me something useful"
When development on Java started in 1991, double-dash long options weren’t as prevalent as they are today.
-version still works:

  $ java -version
  openjdk version "18" 2022-03-22
  OpenJDK Runtime Environment Temurin-18+36 (build 18+36)
  OpenJDK 64-Bit Server VM Temurin-18+36 (build 18+36, mixed mode, sharing)
I think at one point the canonical approach may even have been:

java -D-version

I laugh at verbose options that are:

-v for basic verbose

-vv for more

-vvv for even more

-vvvv oh come on you've got to be kidding

-vvvvv nope, they're not kidding

I keep hoping someone will do this with -v², -v³, and so on.
Where the base value is two and -v³ is a shortcut for -vvvvvvvv? Because it wouldn't work with a base of one (1³=1).

Just assessing expectations because I do like the idea and would implement it (in addition to the expected way) next time it comes up

In my mind, -v³ would be the same as -vvv, and -v⁴ for -vvvv, and on and on.

I suppose you could really take it to some absurd level with -v¹⁰ for -vvvvvvvvvv

The v is log scale, which does make some sense in terms of output volume. ;)
Ah, but you'd have to error on any even power, since of course a negative squared is positive, thus -v^2 would be v^2 and without the dash you can't be sure it's a switch.
There's an easy solution to this: just use i for even exponents.

So (-iv)² = -vv and once you've escaped the brackets in bash all is good.

I think we're on to something here....

Nah exponents have higher precedence than signs, it gets annoying otherwise.

  -vv ⇒ -w
  -vvvv ⇒ -ww
Just a joke :)
And yet… now I am deeply wishing for this. :-)
-w should be equivalent to -uu surely!
Well usually you can use -vvvv -> -vv -vv so if you make your font size small enough that vv looks like a w..
I absolutely hate this convention. Not only is there often very little documentation about what exactly gets added in for each verbosity level, making me guess randomly and then maybe binary search to find what I need with minimal noise, its basically impossible for me to differentiate repeated characters beyond 4 without using a cursor to step though them. I don't have any opposition to fine-grained log levels, but geez, just make it `-v [VERBOSITY (default 1)]` or something sane like that.
I went through this ritual almost every time:

    $ java --version
    Unrecognized option: --version
    $ java -v
    Unrecognized option: -v
    $ java -version
    openjdk version "1.8.0_312"
Looks like this was fixed in JDK 11.

But Java isn't as sadistic as Go lang:

    $ go --version
    [scrolls off screen]
    $ go --version | less
    [scrolls off screen]
    $ go --version 2>&1 | less
    [search for 'version' command]
    $ go version
    go version go1.17.2 linux/amd64
don't forget grep -v:

"-v, --invert-match"

This one is actually really interesting! I would guess that it comes from electrical engineering, and specifically the signal processing side of things where filters happen. One option for filters are “notch filters” [1], and the letter “v” looks like a notch. So just think of “notching-out” a signal when you’re trying to remove something from your grip results.

[1] https://en.wikipedia.org/wiki/Band-stop_filter

Might just be that i was taken for case insensitive.

62 characters is not a lot for tools that have a lot of settings.

In the case of tools like grep, the settings are really more of a command vocabulary, and should rightly be written in their own language in a script file, like sed and awk, but grep makes some especially commonly needed ops available as a simpler command with switches for convenience. And that results in some seemingly arcane and inconsistent commandlines.

Defining how to search for something is just not a simple 2 or 3 options covers it kind of job.

By contrast, another tool with the same problem but clearly originated from a different starting idea is 'find'. It also has to have essentially a vocabulary to express your intentions in composed sentences, and it ends up with a mix of switches and words.

I'd guess that it's probably just that `-i` and `-n` were used for other options, and `-v` is the next letter and a fairly prominent sound in the word.
Perhaps it was simply an available letter, as saghm said, but I've always imagined that at least part of the origin story is that it's a mnemonic for "invert" or "negative".
Don't forget the capital 'V' option, e.g. `python3 -V`

I usually assume that lower-case 'v' is for verbose.

...which is often confused with the switch for verbose
I tend to dedicate -v for version data in my apps, and use a -d(ebug) flag for more verbose logging. Or even follow the VERBOSE env var convention.

With some apps it's damn near impossible to query the version, especially cross platform. I used to manage a database of that syntax with a tool called "specs".

-d is for daemon mode (never default to this)

-p is for PID file

-l is for log file

-v is for version

-L is for verbosity level (e.g.: -L debug)

-c is for config file (where all the other options may be specified instead)

-h is for help

The rest are context-specific.

-f can be for configuration file as well (see: apache httpd, mongod, and sshd)
> Honestly, in practice, I've seen many tools that support -help also allow --help and -h for those who have the muscle memory reflex for those, so it's not nearly as problematic.

  $ javac --help
  javac: invalid flag: --help
  Usage: javac <options> <source files>
  use -help for a list of possible options
:-(
Using double -- for long named flags is a GNU-ism. Java came from Sun and so prefers the single dashes.
But "-help" is just "-h -e -l -p" ...
Which is also a gnuism
That's my point - "-help" violates the gnu standard.
That's his point, Sun has nothing to do with Gnu so they are not bound to their "standards".
the point was that that gnu is not a universal standard
“-help” being equivalent to “-h -e -l -p” is not a GNUism. It’s described by POSIX. If a utility takes the options “-a” and “-o something” and uses POSIX getopt(), then these are all equivalent:

    cmd -ao arg path path
    cmd -a -o arg path path
    cmd -o arg -a path path
    cmd -a -o arg -- path path
    cmd -a -oarg path path
    cmd -aoarg path path
A long time ago I filed a bug with Sun about inconsistent flags on the JDK tooling. As I recall it they fixed the sole specific example that I cited instead of reviewing them all...
the clever way to parse `-help` is to treat it as multiple options, but design your argument handler so that the `help` handler short-circuits and doesn't do anything except output help text and exit (i.e. it reads '-h' then calls the help handler and exits, doesn't matter if -e isn't a valid option).
Wouldn't that make it awkward to combine help with any other option? I guess that's an edge case, but still...
Most commands IME will have this short-circuit behavior

$ cmd --with -a --lot -of --options

(fails)

$ cmd --with -a --lot -of --options --help

(behaves as if --help was the only option)

From a terminal perspective, up-arrow + space + -h is often the fewest keystrokes to get what I want

Whenever I do `cmd -h` or `cmd --help`, and the command fails and asks me to type something else, I always find this a very helpful hint that cmd’s authors don’t have respect for conventions, and that I should be cautious with my expectations from then on.
I agree, but I dunno maybe this is more new school than I realize. I'm willing to accept the possibility that other people have been exposed to conventions I haven't. On my personal projects I stick to this convention though, it just feels like the right thing to do.
same for `cmd -v` `cmd --version`
The first one is verbose, not version, though? Not sure if you're used to a set of utilities that doesn't intersect the ones I'm used to where -v is version. I've seen -V, though.

And then there's grep

(comment deleted)
I agree that -V is more common. I have used a few things that use -v for version though (I think `ruby` does, which led to some confusion for me the first time I tried to pass that to `python` and instead of getting the version number found myself in a more chatty than normal python shell).
Defacto short switch for version is "-V". "-v" is verbose.
As is quite clear in this thread, there really is no unified way of doing things.

Uppercase switches also strikes me as not very intuitive, either you need to look at the help page or you have to have the same mindset as the developer.

And still, the distinction between lowercase and uppercase switches are not easy to remember.

For the power user though it makes sense.

The cat command is rather infamous for using -v to mean “visual” (as in, convert invisible characters to something visible).

But the infamy is not that it used -v for something other than “version”—I doubt that convention existed in 1983, when the complaint was made—but rather that it was a sign of the ever‐growing complexity of specific Unix tools at the expense of the harmony of the whole system.

See “Program design in the UNIX environment,” by Rob Pike and Brian Kernighan, USENIX 1983: http://harmful.cat-v.org/cat-v/

Trouble is that some competing approaches appeared around the same time in history and what is convention depends on what you happened to be exposed to.
Honest question: the BSDs adopted getoptlong() 20 years ago[0], what are people being exposed to that uses -single-dash-long-options?[1]

Or were you referring to older utilities/actual unix times?

[0] https://www.freebsd.org/cgi/man.cgi?query=getopt_long&sektio... [1] I mean, there's oddities such as openssl(1) but those seem a minority on every platform

> what are people being exposed to that uses -single-dash-long-options?

Go's 'flag' package -- although double-dash is silently accepted on the command line.

The deeper issue with 'flag' is that it rejects the BSD convention of a short/long option pair having guaranteed equivalent semantics e.g. -h/--help. The library just won't let the programmer create such a pair by means of its standard functions.

> Go's 'flag' package

Which uses the Plan 9 convention; the system the Go creators were exposed to. A good example of competing conventions of the past rearing itself in modern tools.

Ocaml is notorious for having CLIs that use longform options with a single dash. It’s infuriating. So it would be -help in this example
A few of my college courses used OCaml, and it had lots of conventions like this that I found somewhat odd. If I remember correctly, exceptions (which were not used that often from what I could tell due to preferences for handling errors in a more algebraic manner) are named with casing like `Not_found`, which I don't even know the name for (maybe "capitalized snake-case?), I assume to try to make them resemble the capitalization scheme that sentences use. I also remember finding it quite strange to read types annotated with a space before the colon (e.g. `let x : int in`); a friend told me that this was due to OCaml's authors being French, which unlike English puts spaces in front of colons in prose. Combined with the fact that we were taught only a subset of the language (we never once learned how to use the object system for which the "O" was put in OCaml), and we were processed provided with pre-written build files for projects and not taught much how how to use the build tools, writing OCaml always felt somewhat surreal for me. Overall though, I did learn a lot from those classes, and I think it was a good choice for teaching the concepts the courses were intended to cover (especially the compilers course, which in retrospect I would have found much more tedious if course was taught in C or Java or something).
> I also remember finding it quite strange to read types annotated with a space before the colon (e.g. `let x : int in`); a friend told me that this was due to OCaml's authors being French, which unlike English puts spaces in front of colons in prose.

Maybe, but I find it more likely that they just copied math notation. In mathematics (broadly, not just theoretical CS, also analysis), the type of something is indicated with an infix `:`, like `f : A -> B` is a function from A to B. This colon conventionally has equal spacing on both sides, like a regular infix operator.

That's possible as well. I have no idea about the accuracy of my friend's claim, which is why I relayed it as hearsay rather than stating it as a fact I was sure about.
A lot of the decisions in OCaml seem related to the French language, which adds a space before the : (unlike in english).

There's the "Thing of int" weirdness also

OCaml exception constructors are just term constructors in the open sum type `exn`. In OCaml, to distinguish constructors from bound variables, constructors must begin with a capital letter. Thus `let Foo = 4;;` is an error.
That doesn't explain why they couldn't have used `Not_Found` or `NotFound` instead.
(comment deleted)
sometimes it's because the software existed before the conventions. Such is the case for Xorg.
(comment deleted)
> This pattern is cumbersome to deal with in practice, especially in tools that use subcommands. Instead of typing foo bar -h to get help, you have to move the cursor between foo and bar to insert help: foo help bar in order to get help about the bar subcommand. Then, once you presumably know how to use it, up-arrow, remove help from between the tool and subcommand, move to the end of the line, and continue on.

This is not a pain if you are using the default readline keybindings (which ape those of Emacs): up arrow, M-b to move back one word, type 'help ', hit RET; for the next bit, up arrow, M-b M-b to move back two words (to the beginning of 'help'), M-d to delete forward one word, C-e to go to the end of the line and you're done. No doubt it's similarly easy using the vi keybindings.

That sounds complex, but really it's second nature.

> As in the case of podman above, if you know your user is asking for help, show them the damn help.

The issue there is that it doesn't know the user is asking for help, because the way one asks for help with podman is with --help; -h is meaningless to podman. Note that -h isn't always the flag for help; just off the top of my head, in several command-line tools it is the flag for human-readable file sizes.

> No doubt it's similarly easy using the vi keybindings.

I'd do kbihelp for the first and k2bdwA for the second.

or you can use C-x C-e to edit the command in $EDITOR
Ironically when I tried to run that in vterm in emacs it triggered an Emacs command which failed.
I hate when a program tells me what I have to do. I always think "damn it program, if you know what to do, just do it already. I say what to do, and you do it".

For example when terraform tells me to run "terraform init", as if actually typing the letters on the keyboard had any benefit...

Same thing with Python:

>>> help

Type help() for interactive help, or help(object) for help about object.

>>> exit

Use exit() or Ctrl-D (i.e. EOF) to exit

If you know what I'm trying to do, then just do it!

  >>> print "hi"
  SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)?
I would be in favor of that for this one!
Isn't this due to some REPL-constraints or not wanting to break the way the language works? Maybe there's no way to evaluate the "exit" and "help" objects replaced by "exit()" and "help()", and that making exceptions would clutter the code. Not sure the reasoning behind it, but that's what it seems.
> not wanting to break the way the language works

This is the reason. "help" and "exit" (as well as "quit") are perfectly cromulent variable names in Python. So the REPL does the best possible thing, i.e., try and evaluate the expression and shoot a message if it fails. Case in point:

    >>> help = "hi"
    >>> help
    "hi"
    >>> del help
    >>> help
    Type help() for interactive help, or help(object) for help about object.
Why not:

    - check if a variable called "help" is in scope
    - if not, call help().
    - otherwise, print its value.
Because then when there IS a variable, the help command you learned will not work.

I think anyone crying and baffled about this is fundamentally not well suited to programming. This sort of logical problem should be intuitive.

The seeming irrationality of the special case behavior is just something funny to make your mom laugh, not something that's actually illogical or inconsistent or stupid.

What if you have defined a "help()" function though?

REPL should be as dumb as possible. That's a feature, not a bug.

There’s nothing special about those variables besides them being builtins. Those messages are actually just the __repr__ for each.
You could make `exit` quit the application when __repr__ is called.

Not sure if this is a good idea however.

It doesn't know what you're trying to do, it can just make a best-effort guess, which may be wrong. Maybe you are deep inside a session, trying to inspect a variable or function called `exit` that just doesn't happen to be in scope like you expect? Exiting the process at that point could be terrible and the impact of the lost state exceed the lifetime-accumulated lost seconds that would have been saved by being "helpful".

If you really want this, consider using ipython with %autocall as your Python REPL.

https://ipython.readthedocs.io/en/stable/interactive/magics....

It's worse:

    Type "help", "copyright", "credits" or "license()" for more information.
    >>> help
    Type help() for interactive help, or help(object) for help about object.
    >>>
Python tells you to type "help", but when you do it turns out that that doesn't do much. I get it, they want to make the distinction between help() and help(object), but I feel that could have done a bit more friendly.
My "favorite" one of those is Mercurial's error when you use a subcommand that you need to enable an extension for. Not only does it know the subcommand is valid, it also tells you which extension to enable. If it's gone all that way, why not enable the extension automatically?
I have been trying to google this concept of confusion for years. Finally, an article where someone has had the same thought as me about the consistency. This has been one of those things that's impossible to search for because everything routes into a technical syntax discussion (like a MAN summary page) instead.
Don't forget /?
The only place I've seen this is windows world where /arg and -arg are the same thing. Don't ask me how this came about.
DOS, where /arg was the way
Which it got from CP/M, which borrowed the idiom from VMS.
They originally used - but IBM wanted /
IIRC, it's up to the application whether they handle /arg and -arg forms. They might just as well not support the latter.
-hh is what a major app at work requires. Engineering indeed provides room for creativity.
I want to throw out there that in addition to these parameters and how you call them in different ways, the order of operations for them is also very frustrating.

FFMPEG comes to mind immediately as an example. Essentially, you call ffmpeg to convert media1 with specs and provide media2 as an output for it. I'm mostly understanding and accepting that this ordering matters, because you're applying arguments onto the input instead of trying to do something on the output for some reason.

Where it gets confusing, though, is if you want to resize and crop an image for example. You may end up with different results depending on the order you specify these operations.

Maybe this particular use case makes sense because resizing and cropping hard-coded coordinates could be confusing. However, other operations that seem like they shouldn't interfere with each other sometimes do.

It would be nice to see some type of handling so there isn't this type of confusion. Perhaps some type of --override command, otherwise default to a consistent output regardless of order.

In contrast, I can't think of any issue I've had with "ls". I like that -l -a -t -r can be combined into -latr, but it does make learning the terminal very confusing for beginners when this isn't always supported or consistent in other programs.

> Where it gets confusing, though, is if you want to resize and crop an image for example. You may end up with different results depending on the order you specify these operations.

Could you clarify, what's confusing about it? The operations in ffmpeg are sequential, unless you use advanced chaining capabilities. If you look at a crop as a substraction, and at a resampling as a multiplication, it becomes evident, how the order affects the result.

(24 - 4) * 0.25 = 5 24 * 0.25 - 4 = 2

> As in the case of podman above, if you know your user is asking for help, show them the damn help.

Since (as other comments say) you can never know for sure that the user is asking for helo, the only sane way to actually implement this is to show the "usage" message on every incorrect invocation of the command.

This has two drawbacks, however:

* It makes the output of an incorrect invocation much longer. Personally, I prefer the 2-line output approach (1 line for the error, 1 explaining how to ask for help)

* You still need to have an explicit help command, because I sure as hell don't want to craft an intentionally incorrect invocation every time I want to see the usage message.

My 2 cents: just use "--help/-h" or a "help" subcommand. They are by large the most popular ways to check out usage, no need to be creative here.

This post resonated with me and the inconsistencies certainly don’t add to the already bad discoverability of CLI arguments. Personally, I find using -h/—-help the most sane way (YMMV).
(comment deleted)
(comment deleted)
Learn to read manuals, not blogs or Q&A sites.

POSIX.1-2017 https://pubs.opengroup.org/onlinepubs/9699919799/

GNU Manuals Online https://www.gnu.org/manual/

Linux man pages online https://man7.org/linux/man-pages/index.html

Ubuntu Manpage Repository https://manpages.ubuntu.com

Reading UNIX Manual Pages | Apple Developer Documentation https://developer.apple.com/documentation/os/reading_unix_ma...

Windows Commands https://docs.microsoft.com/en-us/windows-server/administrati...

Is or was -q ever used for help? Or is this a weird thing one of my coworkers started?
Some apps don't even provide a help menu. They may come with a man page.
And some come with dozens of man pages, several of which need to be combined to find the syntax allowed by certain commands (often also needing a help command)! OpenSSL is bad in this way.
"You: Hi! I won! Here's my ticket! Where do I collect my winnings?"

You think you are talking to the clerk that will initiate the payout but actually you are talking to the machine that made the draw.

When you try -h or --help then the result can be nice or not. In general the author gives quite a lot of pointers. However the docs are where it is at and that is from man or Help -> etc.

If the docs are provided and if you can't be arsed to read the docs then bugger off! Now this is where it gets tricky. Not all programmers are decent writers of docs nor are all potential consumers of docs decent readers.

Now OP is whittering on about incantations requesting help. They only demonstrate a few examples so eventually one of those incantations might work.

The important thing is to ensure that a request for help does one of two things: provide help or no op.