1. 93
  1. 32

    --version/--verbose along with -v and -V is another set of flags that drives me crazy because it’s not standardized (especially with some programs which only provide the short flags).

    On a side note I do think that -? is an odd translation from Windows land. With Windows command line arguments, /? is more common which is way easier to type.

    EDIT: Updating this to be more constructive - if you’re designing a command line program, please consider including both --version and --verbose. I think -v is generally verbose and -V is generally version. They’re not as consistent, but if you provide short options, I’d recommend those.

    1. 4
      [justin.blank@localhost tms-app]$ java --version
      openjdk 11.0.14 2022-01-18
      OpenJDK Runtime Environment 18.9 (build 11.0.14+9)
      OpenJDK 64-Bit Server VM 18.9 (build 11.0.14+9, mixed mode, sharing)
      [justin.blank@localhost tms-app]$ java -version
      openjdk version "11.0.14" 2022-01-18
      OpenJDK Runtime Environment 18.9 (build 11.0.14+9)
      OpenJDK 64-Bit Server VM 18.9 (build 11.0.14+9, mixed mode, sharing)
      [justin.blank@localhost tms-app]$ java -v
      Unrecognized option: -v
      Error: Could not create the Java Virtual Machine.
      Error: A fatal exception has occurred. Program will exit.
      

      I believe prior to version 8.x.y, --version would fail, but -version would work.

      1. 3

        I believe prior to version 8.x.y, –version would fail, but -version would work.

        Yeah, Java uses single-dash “long” options. Even today I think it was only --version that was special-cased; the rest are still single-dash only. For example, java -classpath works but java --classpath does not.

        I’d be curious about the history behind this. Although the linked post calls the short/long options distinction POSIX, I believe double-dash long options originated as a GNU convention. I could imagine 1990s Sun not being interested in GNU conventions. This is complete speculation though.

        1. 2

          X does too. I suspect people needed longer options only in late 80s/early 90s, and X did it before GNU. Even then, the longer options call back Multics.

      2. 4

        I used docker-compose down -v for years and thing that it gave me verbose output. Turn out that:

        • with docker-compose -v it means prints version and exit
        • with docker-compose down -v it means removed named volumes
        1. 3

          Don’t get me started on tools which need you to run programname help version

        2. 24

          Then there’s a whole different help document in the man file.

          1. 19

            Sometimes --help opens a pager with the man file.

            Then there’s the GNU info system; info cat is a whole different document than man cat.

            1. 5

              “Modern” software doesn’t tend to come with a man page IME, and most of the new package managers don’t even have a mechanism for packages to provide man pages. Increasingly, documentation websites and a --help/-h/-help/help flag/subcommand is the only documentation you’ll get.

              1. 13

                I think this is because people can lie to themselves that their website is adequate documentation, but it’s harder to be equally self deluded when you have to write a text only man page. A couple exhortations and an example look so much less impressive stripped of hero graphics.

                1. 4

                  Yes. I basically agree with this trend. Man is one too many ways to do it. Everything should just support -h/--help and include a prominent URL at the top if there’s more help than can fit in there.

                  1. 26

                    I’m exactly the opposite. My first instinct is always man <command> generally because I want more info than -h/--help should provide. I always get very annoyed when a tool doesn’t come with manpages. --help isn’t sufficient imo.

                    1. 10

                      Especially when the site disappears from the web a few years later.

                      1. 1

                        I don’t want the accessibility of documentation to depend on an external program.

                        1. 1

                          I’m confused, are you referring to a web browser or man(1) here? Or both, and you’re advocating plain text docs?

                          1. 2

                            I guess both, but it was primarily aimed at man. If the program just spits out its help, you can pipe it into your favorite pager and be happy. Having a man page creates a dependency and limits to program to being installed by the system package manager.

                      2. 20

                        No, please don’t do that. I spend most of my day working on an air-gapped system and going to a URL simply isn’t straightforward. Don’t just assume people have an Internet connection. Also, the version of a man page will always match the version of the installed software.

                        It’d be better if there were usage and version commands that would be like man but output basic usage only and version details, respectively.

                        1. 4

                          There’s tldr. No idea if it works behind an air gap, but I guess you could download the database locally.

                        2. 3

                          If I had to give a one word advice on how to become a hacker, that would be “manpages”. Unix mastery of those who red manpages is a whole other level than those who think piping to grep with simple string matching isnan advance hack.

                        3. 1

                          Is there a manpage writing flow that you prefer? Every time I’ve wanted to write a manpage I’ve shied away. I usually settle with writing Markdown or HTML documentation and just shipping that instead.

                          1. 3

                            You can use pandoc to convert from Markdown to man pages. It grabs some of the details from a magic title line (search for pandoc_title_block on the page).

                            1. 1

                              I’ve done that in the past but usually end up just converting it to HTML instead. I wish there was a version of man that didn’t rely on troff/groff and didn’t use man’s somewhat baroque section system, but there’s not much else in its place. I have really enjoyed using CHM files in the past for offline documentation. For long trips without connectivity (e.g. train, plane) I’ve downloaded language and library docs in the past and chugged along on projects.

                            2. 2

                              I tend to just write mandoc directly and use the lint option of mandoc to check it (I have now started adding it to CI, so man pages get checked on commit) but LLVM uses Sphinx to generate the man pages. The Sphinx docs are a lot easier to edit than mandoc (troff macros) and seem to generate good output, but they require a separate toolchain to build the man pages so you either need that as part of your build flow or you need to commit the generated pages to your source repo.

                        4. 21

                          It took me many years into my carreer to learn that in bash you can do $ help <builtin>, e.g. $ help read. Using this provides you with great docs on the command whereas <builtin> -h just provides a terse summary of command line options.

                          1. 3

                            This is a revelation. I usually end up either searching “man bash” or (in more recent years) just googling if I need help on a builtin.

                          2. 9

                            I support these on most of my scripts:

                            -h
                            --h
                            -help
                            --help
                            

                            Things such as --? or -? feel too Winblows to me - kinda like its /? switch.

                            1. 5

                              The problem with -help is that supporting it prevents you from supporting passing -h -e -l -p as -help, which breaks the short-option convention of most UNIX systems.

                              1. 2

                                -? is actually more common on much older Unix stuff.

                                1. 1

                                  I’m curious. Do you have examples?

                                  1. 1

                                    I’m curious. Do you have examples?

                                    Just try all the basic Unix commands on a Solaris or BSD system, things like cat, df, diff, grep, nm, ls. It is likely also true for other real Unix systems. Linux and GNU seem to have standardised more on –help and -h so -? rarely works there. Reading a blog that follows up to this article, it seems there’s an underlying reason to this lying in how getopt works: https://utcc.utoronto.ca/~cks/space/blog/unix/GetoptQuestionOptionForHelp

                              2. 8

                                I once ran shutdown --help on a machine that was serving over 100 users in an office (when people logged into UNIX machines and ran terminal based applications). It just shut down. I say ‘just’ - the process took over 10 minutes. It then took another 40 minutes to boot again.

                                That was the day I stopped just trying stuff to see what happens.

                                Just kidding, of course I still do!

                                1. 2

                                  [ big oof ]

                                  I thought this was a bad time

                                  > git stash save help
                                  Saved working directory and index state On main: help
                                  > git stash list
                                  stash@{0}: On main: help
                                  

                                  But shutdown --help is worse. :( Hard earned learning. :)

                                  1. 1

                                    Sounds like me trying to see if I can what install does on esxi by running install --help, which turns out is a Shell script that’s responsible for setting up the entire installation by starting some ncurses interface. Thankfully after reading the source, kill -9 was all that saved the day.

                                  2. 7

                                    In addition to that printing help pages to stderr is so annoying. It’s all such a beautiful mess.

                                    1. 9
                                      $ foo --help
                                      <10 pages of help>
                                      
                                      $ foo --help | less
                                      <10 pages of help with less drawn ontop>
                                      
                                      $ foo --help 2>&1 | less
                                      <success!>
                                      

                                      :/

                                      Now what was I looking for again?

                                      1. 2

                                        help going to stderr always makes me very angry!

                                        1. 2

                                          I have the same reaction when it happens to me… but I still do it when writing these kinds of tools. Sorry.

                                          Two reasons:

                                          1. Help text in stdout really messes with piped output, as sjamaan has beaten me to pointing out
                                          2. I usually default to showing help text whenever the program encounters unexpected or malformed flags. Partly to catch people typing “help” in unexpected ways
                                          1. 4

                                            For me, usage is different than help. Usage is a short message saying the options are wrong and here’s a small summary of the syntax, help is 10 pages long and exhaustive. I’m fine with usage going to stderr, but not help.

                                            1. 3

                                              I agree, the use case that absolutely should go to stdout is when you call help directly, so it is easy to pass to a pager, e.g.:

                                              $ fdisk --help | less
                                              

                                              In this case there are no errors, so why would you write to stderr?

                                              1. 1

                                                This is very fair and it probably tells you something about the size of CLI apps I normally write that usage and help are usually the same thing!

                                        2. 6

                                          It’s helpful (har har) when you’re piping the output of a command to another command, and it doesn’t understand one of the flags (because of version or Unix flavour differences) and prints its help. Otherwise you’ll get very weird results where the next command in the pipeline is trying to parse the help output of the first command.

                                          1. 1

                                            I do actually think that’s the ideal outcome. If I’ve misused a flag I’d like the entire pipeline to fall over. I might not be able to trust bash to emit an error message but a complete nonsense output would be a clearer sign that something strange has happened than output that is subtly off, and if I’m lucky then whatever fragments of help text make it to the end might even include the name of the command I got wrong.

                                          2. 1

                                            Oh good heavens. It blows my mind how frequently I run into apps that do this. How do so many people do this without noticing how annoying it is?

                                          3. 6

                                            I hate modern systems changing -- to an em-dash . That’s the one time that I curse gnu for adding that format of long option.

                                            Fine, c-x,c-e, search and replace, execute.

                                            1. 2

                                              Wait, shells do that?

                                              If it’s in documentation, commands should be semantically different from other text.

                                              1. 2

                                                Sorry, not shells, but many other places, like LaTeX, macos smart quotes and dashes, and most word processing suites. It’s often the first thing I turn off…

                                            2. 5

                                              I wish there was a standard way to embed help documentation in binaries and/or scripts that could be extracted with a standard utility. You might have something as useful as a man page, but still available in a just-the-binary deployment.

                                              Of course, it would have to be different for each scripting language, so the utility would have to know the format for each one, or the interpreter on the shebang line would need a standard flag to dump the help text. But then we’re back at square one…

                                              1. 5

                                                Tangent, just because: tar doesn’t need even a single - for the main cvtfxzj (etc) options, either on macOS or Linux:

                                                $ tar jcvf archive.tbz file1 file2
                                                a file1
                                                a file2
                                                
                                                $ tar jtvf archive.tbz
                                                -rw-r--r--  0 user   group       0 Apr 11 19:45 file1
                                                -rw-r--r--  0 user   group       0 Apr 11 19:45 file2
                                                

                                                Just think of all the unnecessary dashes being typed around the world, every minute. Hell, every SECOND.

                                                1. 3

                                                  Tar should just go all the way and just have random numbers for common (?) groups of options. tar 243 file.tar.gz; tar 932 file.tar.gz -- output etc. It would be easier to remember.

                                                  1. 8

                                                    chmod effectively has arbitrary numbers for options. At least for those of us who don’t know octal.

                                                    “644” and “755” are complete verbs to me. Or “777” (roughly translates to “amateur hour”).

                                                    1. 2

                                                      Funilly enough, chmod doesn’t take -h as a short opt :)

                                                      A heads-up, but you can e.g. chmod +-rwx (read-write-execute) stuff. E.g. add read: chmod +r file, or remove exec perms: chmod -x file. You can also specify user/group/others/all (default is all if you don’t specify). E.g. group can read and execute: chmod g+rx file. Also add -R to go recurrsively and you’re golden.

                                                      P.S. just wanted to add that octal is simple enough as well, but I guess I’m speaking with 30 years of experience so it’s not really fair.

                                                    2. 2

                                                      I have an e function in my zshrc that understands all archive formats and extracts them. I just need to remember e ;p

                                                      1. 2

                                                        FreeBSD’s tar uses libarchive and so mostly ignores the other flags if you pass x - it will figure out what the file format is from the header and then extract it. You can pass z or J or whatever to tell it that it’s gzip or bzip2 or xz compressed, but you don’t need to.

                                                        1. 1

                                                          aunpack is also such a command.

                                                        2. 1

                                                          Just use the mnemonics:

                                                          tar xaf — extract a file

                                                          tar caf — create a file

                                                      2. 4

                                                        I think POSIX only specifies the short syntax, but most command line parsers support long arguments as an extension.

                                                        1. 2

                                                          ah yes you’re absolutely right! I added an edit note in the post, thanks for pointing that out.

                                                        2. 4

                                                          This is something that was less of a problem before Unix. VMS, for example, parsed command options before handing them to commands. (Anecdotally, you can actually learn how to use VMS from a terminal by typing help. I don’t think I could do the same on Unix.)

                                                          1. 4

                                                            This is something that was less of a problem before Unix. VMS, for example, parsed command options before handing them to commands.

                                                            This is one thing I like about PowerShell: while they do use the -flag format (as opposed to the more standard --flag) which I detest (I guess they were copying Perl on that?), argument parsing is very much integrated into the language, and it is absolutely trivial to add arguments to a script. Example:

                                                            param (
                                                                [Parameter(ValueFromPipeline = $true)]
                                                                [string]$foo,
                                                                [alias('f')]
                                                                [double]$bar = DEFAULT_VALUE,
                                                                [alias('b')]
                                                                [double]$baz = ANOTHER_DEFAULT,
                                                                [alias('z')]
                                                                [switch]$myflag,
                                                                [alias('m')]
                                                            )
                                                            

                                                            Much easier than using getopt to parse arguments in bash. And you get niceties like type checking, etc for free!

                                                            1. 2

                                                              I always suspected the single-dash flag syntax might be a little conscious effort not to look too much like bash.

                                                              1. 2

                                                                OpenStep / Cocoa also have a nice model here, with exactly the same issue as PowerShell (I strongly suspect this is where PowerShell got its inspiration). Any command-line flags that you pass to an OpenStep program are added to the program’s user defaults in the NSArgumentDomain domain. This gives a consistent interface to things that are either stored in a config file or passed as arguments and allows arguments to override config file things. It’s one of the nice corners of OpenStep that I wish other *NIX systems had copied (though I’d be happier if they’d used the GNU long options convention).

                                                              2. 3

                                                                Early (and probably later versions) of VMS/DCL used 4 bytes (one 32 bit word) for the commands…. and so long as you got the first four chars right… it didn’t give a shit what you typed for the rest of them!

                                                                Was somewhat miffed when I discovered that after (at least thinking) I was being so very careful for years…

                                                                “help” is a Unix shell builtin command that gives you help on other shell builtins.

                                                                1. 2

                                                                  I recently coded a little tool for the Amiga, and using ReadArgs(), as part of the OS, immediately gave my little tool the same robust command line parsing as every other command line tool, with the same standardised format and the same standardised (terse) help format. Meanwhile, Unix commands still can’t agree what command line options should look like, not to mention how to parse them.

                                                                2. 3

                                                                  /?

                                                                  1. 2

                                                                    %r{\A-+(h(e(lp?)?|?+)\z}i

                                                                    What’s the problem?

                                                                    1. 2

                                                                      On this topic, one of my pet peeves is the wide variance among two common user actions: filtering out, and printing just filenames.

                                                                      • --ignore-dir, --exclude-dir, --except, --exclude, --ignore
                                                                      • --only-name, --only-names, --name-only, --names-only, --files-with-matches
                                                                      1. 1
                                                                        All right, you win.
                                                                        
                                                                                                       /----\
                                                                                               -------/      \
                                                                                              /               \
                                                                                             /                |
                                                                           -----------------/                  --------\
                                                                           ----------------------------------------------
                                                                        

                                                                        What is it? It's an elephant being eaten by a snake, of course.

                                                                        1. 1

                                                                          -v –verbose as well…