I don't think the shell/utilities in historical Unix nor in something as "recent" as 4.4BSD supported using a double-dash(or two consecutive hyphens) as an end of options delimiter. With FreeBSD, you can see for instance a note introduced in the rm manpages with the 2.2.1 release(1997). But this is just the documentation for one command.

Looking at the oldest GNU fileutils changelog I can find, I see this1(slightly altered):

Tue Aug 28 18:05:24 1990  David J. MacKenzie  (djm at albert.ai.mit.edu)

* touch.c (main): Don't interpret first non-option arg as a   <---
  time if `--' is given (POSIX-required kludge).  
* touch.c: Add long-named options.
* Many files: Include <getopt.h> instead of "getopt.h" since
  getopt.h will be in the GNU /usr/include.
* install.c: Declare some functions.
* touch.c, getdate.y, posixtime.y, mktime.c: New files, from bin-src.
* posixtime.y: Move year from before time to after it (but
  before the seconds), for 1003.2 draft 10.

This predates Linux. It's clearly to account for the fact that you might want to create a file with a name containing the same number of digits as a time specification(eight or ten-digit decimal number) - rather than specifying a timestamp for an existing file...

  • So is it posix.1 which introduced the double-dash (--) as an end of options delimiter in Unix shells?
  • Did this all start because some people wanted to use digits in filenames with touch in the early '90s and then this went on in a piecemeal fashion one utility at a time for a decade??
  • What is the spirited comment in the changelog about?
  • When was Guideline 10(The argument -- should be accepted as a delimiter indicating the end of options.[...]) introduced to the POSIX Utility Syntax?

1. As opposed to this i.e. documenting the long options in all commands usage globally, which is unrelated. On the other hand, you can see reference to the delimiter appear in something like GNU rm.c in 2000 as a comment, before being exposed to the end user in 2005(the diagnose_leading_hyphen function). But this is all much later and is about a very specific use case.

  • 1
    BSD4.3RENO at least had a getopt that supported --. Jul 29, 2014 at 6:55
  • @StéphaneChazelas You also made a comment about getopt not being the only api able to deal with the delimiter. Does that mean that this had been provided for and worked before it was actually being used?? I'm afraid this is beyond me. Thank you!
    – user44370
    Jul 29, 2014 at 8:00
  • 2
    It was probably used on an ad hoc basis by several random programs but I think it first became documented when getopt was written in the early 1980's. If someone can get the getopt paper from Uniforum '85, that might give some history. Jul 29, 2014 at 8:08
  • 2
    @MarkPlotnick, actually the getopt as found on SysIII (1980) supports --. Jul 29, 2014 at 9:36

1 Answer 1


As far as I can tell, the use of -- as end-of-options-marker starts with sh and getopt in System III Unix (1980).

According to this history of the Bourne Shell family, the Bourne Shell first appeared in Version 7 Unix (1979). But it didn't have a way for set to separate options from arguments. So the original Bourne shell could do:

  • set -e - turn on exit-on-error mode
  • set arg1 arg2 ... - sets the positional parameters $1=arg1, $2=arg2, etc.

But: set arg1 -e arg2 would give you $1=arg1, $2=arg2, and turn on exit-on-error. Whoops.

System III Unix (1980) fixed that bug and introduced getopt. According to getopt's man page:

   getopt - parse command options

   set -- `getopt optstring $∗`

   Getopt is used to break up options in command lines for easy parsing by
   shell procedures, and to check  for  legal  options.   Optstring  is  a
   string  of  recognized  option letters (see getopt(3C)); if a letter is
   followed by a colon, the option is expected to have an  argument  which
   may or may not be separated from it by white space.  The special option
   -- is used to delimit the end of the options.  Getopt will place --  in
   the  arguments  at  the  end  of  the  options, or recognize it if used
   explicitly.  The shell arguments ($1 $2 . . .) are reset so  that  each
   option  is  preceded  by a - and in its own shell argument; each option
   argument is also in its own shell argument.

As far as I can tell, that's the first place it appears.

From there, it seems that other commands adopted the -- convention to resolve argument parsing ambiguities (such as the examples with touch and rm you cite above) throughout the wild, standardless days of the 1980s.

Some of these piecemeal adoptions were codified in POSIX.1 (1988), which is where the changelog comment about the "POSIX-required kludge" comes from.

But it wasn't until POSIX.2 (1992) that the Utility Syntax Guidelines were adopted, which contain the famous Guideline 10:

Guideline 10:    The argument "--" should be accepted as a delimiter
                 indicating the end of options.  Any following
                 arguments should be treated as operands, even if they
                 begin with the '-' character.  The "--" argument
                 should not be used as an option or as an operand.

And that's where it goes from being a "kludge" to a universal recommendation.

  • Thank you for taking the time! I had mostly ignored getopt in my "research" as I don't grasp why that sort of abstracted utility/function is required. Now I read this was reegineered (getopts) at some point to deal with blanks etc as sysv's getopt couldn't. I will read more about it! Thanks again!
    – user44370
    Aug 1, 2014 at 3:06
  • 5
    If you don't grasp why a standard utility for parsing command-line options would be useful, maybe you haven't tried writing a shell parser for command-line options? It's kind of a pain! Sure would be nice if some other tool did this for me... Also, keep in mind: in 1980 there was no Python, no Ruby, no Java, no Perl, no PHP - even C++ had yet to be invented, and the entire idea of "shell scripting" was still pretty new. So the idea of a standard command-line parser was still pretty novel!
    – wwoods
    Aug 6, 2014 at 16:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy