Quando e como o traço duplo (-) foi introduzido como um delimitador de fim de opções no Unix / Linux?

49

Eu não acho que o shell / utilitários no Unix histórico nem em algo tão "recente" quanto o 4.4BSD suportasse o uso de um traço duplo (ou dois hífens consecutivos) como um delimitador de final de opções . Com o FreeBSD , você pode ver, por exemplo, uma nota introduzida nas rm páginas de manual com a versão 2.2.1 (1997). Mas esta é apenas a documentação para um comando.

Olhando para o changelog mais antigo do arquivo GNU que posso encontrar, vejo este 1 (ligeiramente alterado):

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.

Isso é anterior ao Linux . É claramente necessário levar em consideração o fato de que você pode querer criar um arquivo com um nome que contenha o mesmo número de dígitos que uma especificação de tempo (número decimal de oito ou dez dígitos) - em vez de especificar um carimbo de data e hora para um arquivo existente ...


  • Então, foi o posix.1 que introduziu o traço duplo ( --) como um delimitador de fim de opções nos shells do Unix?
  • Tudo isso começou porque algumas pessoas queriam usar dígitos nos nomes de arquivos touchno início dos anos 90 e isso continuou de forma fragmentada, um utilitário por vez durante uma década?
  • Sobre o que é o comentário espirituoso no changelog?
  • Quando a Diretriz 10 ( O argumento - deve ser aceito como delimitador, indicando o final das opções.) [...] ) foi introduzida na sintaxe do utilitário POSIX ?

1. Em oposição a isso, ou seja, documentando as opções longas em todos os comandos de uso global, o que não é relacionado. Por outro lado, você pode ver referência ao delimitador aparecem em algo como GNU rm.c em 2000 como um comentário, antes de ser exposto para o usuário final em 2005 (o diagnose_leading_hyphen função). Mas tudo isso é muito mais tarde e trata de um caso de uso muito específico.

Gilles 'SO- parar de ser mau'
fonte
11
BSD4.3RENO tinha pelo menos um getoptsuporte --.
Stéphane Chazelas
@ StéphaneChazelas Você também fez um comentário sobre a getopt não ser a única API capaz de lidar com o delimitador. Isso significa que isso foi fornecido e trabalhado antes de ser realmente usado? Receio que isso esteja além de mim. Obrigado!
2
Provavelmente foi usado ad hoc por vários programas aleatórios, mas acho que foi documentado pela primeira vez quando getoptfoi escrito no início dos anos 80. Se alguém puder obter o artigo da Uniforum '85, isso pode dar um pouco de história.
21815 Mark-Plotnick
2
@ MarkPlotnick, na verdade o getopt encontrado em SysIII (1980) suporta --.
Stéphane Chazelas

Respostas:

38

Tanto quanto posso dizer, o uso de --como marcador de fim de opções começa com she getoptno System III Unix (1980).

De acordo com essa história da família Bourne Shell , o Bourne Shell apareceu pela primeira vez na Versão 7 Unix (1979). Mas ele não tem um caminho para seta separar opções de argumentos . Portanto, o shell Bourne original poderia fazer:

  • set -e - ativar o modo de saída com erro
  • set arg1 arg2 ...- define os parâmetros de posição $1=arg1, $2=arg2etc.

Mas: set arg1 -e arg2daria a você $1=arg1, $2=arg2e ativar a saída com erro . Ops.

O System III Unix (1980) corrigiu esse bug e o introduziu getopt. De acordo com getopta página do manual :

NAME
   getopt - parse command options

SYNOPSIS
   set -- `getopt optstring $∗`

DESCRIPTION
   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.

Até onde eu sei, esse é o primeiro lugar que aparece.

A partir daí, parece que outros comandos adotaram a --convenção para resolver ambiguidades de análise de argumentos (como os exemplos com touche rmvocê cita acima) ao longo dos dias selvagens e sem padrões da década de 1980.

Algumas dessas adoções fragmentadas foram codificadas no POSIX.1 (1988), que é de onde vem o comentário do registro de alterações sobre o "kludge necessário para o POSIX".

Mas foi apenas no POSIX.2 (1992) que as Diretrizes de sintaxe de utilitário foram adotadas, que contêm a famosa Diretriz 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.

E é aí que passa de ser um "clamor" a uma recomendação universal.

bosques
fonte
Obrigado por tomar o tempo! Na maioria das vezes, ignorei o getopt em minha "pesquisa", pois não entendo por que esse tipo de utilidade / função abstraída é necessária. Agora eu li que isso foi re-coordenado (getopts) em algum momento para lidar com espaços em branco etc., como o sysv's getoptnão podia. Vou ler mais sobre isso! Obrigado novamente!
5
Se você não entender por que um utilitário padrão para analisar opções de linha de comando seria útil, talvez você não tenha tentado escrever um analisador de shell para opções de linha de comando? É meio que uma dor! Certamente seria bom se alguma outra ferramenta fizesse isso por mim ... Além disso, lembre-se: em 1980, não havia Python, Ruby, Java, Perl ou PHP - mesmo o C ++ ainda não tinha sido inventado e o toda a ideia de "script de shell" ainda era bastante nova. Portanto, a ideia de um analisador de linha de comando padrão ainda era bastante nova!
wwoods