short options are bad

    doesn't allow for future generic parameters
        like adding --null to all appropriate utilities.
        -0,-z,-Z used inconsistently across utils.

short options with (optional) parameters are evil

    spaces are not allowed between short option and optional parameter
    which can be very confusing. For e.g.

    printf "1\0002\000" | xargs -0i replace echo replace   # fails explicitly (not too bad)
    printf "1\0002\000" | xargs -0ireplace echo replace    # "correct" form of above
    printf "1\0002\000" | xargs -i0 echo '{}'              # fails silently (evil)
    printf "1\0002\000" | xargs -i -0 echo '{}'            # "correct"

    It's much clearer when long options are used:

    printf "1\0002\000" | xargs --null --replace         echo '{}'
    printf "1\0002\000" | xargs --null --replace=replace echo replace

non standard options are eeveel

    Apart from making users learn esoteric option formats,
    it precludes the use of standard logic to set and parse options.
    You might think option parsing code is easy, but it's not.
    Consider that pr -T9 used to break until end of 2002,
    but pr -9T was OK.

    One should always try to use getopt or popt.
       Much simpler to code, standard params.
       Definitely if you have more than one optional parameter
       as you can't rely on parameter position.
       libpopt gives you even more general code like allowing
       users to define aliases for options.

    [update 22 May 2006] I noticed the following in procps 2.0.17
    which really needs to be documented. I was trying to output %CPU
    from the ps command when I noticed that:

       ps -e -o pcpu=,args= #fails
       ps -e -o pmem=,args= #works
       ps -e -opcpu=,args=  #works
       ps -e -o pcpu,args   #works

    Note the '=' without an argument is used to suppress the
    header for a field and is not documented in the man page BTW.

    Anyway I went digging as to the cause of this and noticed
    the following nugget in the code:

       /* Unix98 has gross behavior regarding this. From the following: */
       /*            ps -o pid,nice=NICE,tty=TERMINAL,comm              */
       /* The result must be 2 columns: "PID NICE,tty=TERMINAL,comm"    */
       /* Yes, the second column has the name "NICE,tty=TERMINAL,comm"  */
       /* This parser looks for any excuse to ignore that braindamage.  */

    So in summary the failing command above has the surprising/broken/insane UNIX98 behaviour.
    IMHO procps did the following incorrectly:

       1. It implemented this broken UNIX98 behaviour. I really don't see
          UNIX98 really meaning that and at least I can't see any existing scripts
          relying on that insanity.
       2. It broke the rule of least surprise. Notice how the 2nd command above works?
          That shows that this lunacy only applies to certain output specifiers!
          So what, there should be consistent brokeness across all output specifiers.
          Also notice how the 3rd command works because UNIX98 doesn't specify
          that a space is allowed supposedly. Obvious huh!