8

Someone once told me there was a standard when it comes to parsing options on the command line. Something like:

./script.sh [options/flags] [command or file]

I understand that when parsing a shell script this makes life easier since you can shift through the flags and anything left can be accessed by $@ or $*, but is there an actual written standard?

Most programmes I've looked at follow this standard, but there are some exceptions, eg ls where ls -l /path, ls /path -l and ls /path -l /path2 are all acceptable.

4
  • I think options after arguments is non-posix and -- can be used to specify no further options to follow...
    – Sundeep
    Commented Jan 10, 2017 at 6:56
  • but they help, for ex: if I forgot an option, I can simply add it to the end from previous command
    – Sundeep
    Commented Jan 10, 2017 at 6:58
  • ls Documents -l will return the short form listing of the Documents folder along with the error ls: -l: No such file or directory on systems not using GNU ls.
    – Kusalananda
    Commented Jan 11, 2017 at 15:38
  • Related: Why does my ls --help not work? Commented Jan 11, 2017 at 15:56

2 Answers 2

8

The POSIX Base Definitions has a section on "Utility Conventions" which applies to the POSIX base utilities.

The standard getopts utility and the getopt() system interface ("C function") adheres to the guidelines (further down on the page linked to above) when parsing the command line in a shell script or C program. Specifically, for getopts (as an example):

When the end of options is encountered, the getopts utility shall exit with a return value greater than zero; the shell variable OPTIND shall be set to the index of the first operand, or the value "$#" +1 if there are no operands; the name variable shall be set to the character. Any of the following shall identify the end of options: the first -- argument that is not an option-argument, finding an argument that is not an option-argument and does not begin with a -, or encountering an error.

What this basically says is that options shall come first, and then operands (your "command or file").

Doing it any other way would render using getopts or getopt() impossible, and would additionally likely confuse users used to the POSIX way of specifying options and operands for a command.

Note that the abovementioned standard only applies to POSIX utilities, but as such it sets a precedence for Unix utilities in general. Non-standard Unix utilities can choose to follow or to break this, obviously.

For example, the GNU coreutils, even though they implement the standard utilities, allows for things like

$ ls Documents/ -l

if the POSIXLY_CORRECT environment variable is not set, whereas the BSD version of the same utilities do not.

This has the consequence that the following works as expected (if you expect POSIX behaviour, that is) on a BSD system:

$ touch -- 'test' '-l'

$ ls -l test -l
-rw-r--r--  1 kk  kk  0 Jan 11 16:44 -l  
-rw-r--r--  1 kk  kk  0 Jan 11 16:44 test

But on a GNU coreutils system, you get

$ ls -l test -l
-rw-r--r-- 1 kk kk 0 Jan 11 16:44 test

However:

$ env POSIXLY_CORRECT=1 ls -l test -l

and

$ ls -l -- test -l

will do the "right" thing on a GNU system too.

0
4

tl;dr

an example

All three of the option parsing libraries I have worked with in python default to allowing interspersed arguments and provide an illustration of what is common:

  1. The now deprecated python standard library module optparse allows:

    OptionParser.enable_interspersed_args()
    

    Set parsing to not stop on the first non-option, allowing interspersing switches with command arguments. This is the default behavior.

  2. The current python standard library module argparse allows (and only allows) interspersed arguments.

  3. click, the library I am currently favoring, allows interspersed arguments to be disabled:

    click.Context(allow_interspersed_args=False)
    

    But discusses this possibility in the advanced section under trouble shooting unknown args to sub-commands.

3
  • 1
    that is not an answer you can put that in comment, or explain little more further Commented Jan 10, 2017 at 7:05
  • 2
    The question is: Is there an actual written standard? What did I miss? Commented Jan 10, 2017 at 7:09
  • 1
    The standard applies to the POSIX utilities, it's not a standard for all command-line tools in a POSIX-compliant system (although it is useful to know). Commented Jan 10, 2017 at 7:16

You must log in to answer this question.