Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 14 May 2000 11:09:00 +0100
From:      Mark Ovens <mark@ukug.uk.freebsd.org>
To:        cjclark@home.com
Cc:        Erik Trulsson <ertr1013@student.csd.uu.se>, questions@freebsd.org
Subject:   Re: getopt(1) or getopts(1)?
Message-ID:  <20000514110900.B232@parish>
In-Reply-To: <20000513013931.C39310@cc942873-a.ewndsr1.nj.home.com>; from cjc@cc942873-a.ewndsr1.nj.home.com on Sat, May 13, 2000 at 01:39:31AM -0400
References:  <20000511231319.C1522@parish> <20000512084656.A1146@student.csd.uu.se> <20000512183403.A233@parish> <20000513013931.C39310@cc942873-a.ewndsr1.nj.home.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sat, May 13, 2000 at 01:39:31AM -0400, Crist J. Clark wrote:
> On Fri, May 12, 2000 at 06:34:03PM +0100, Mark Ovens wrote:
> > On Fri, May 12, 2000 at 08:46:56AM +0200, Erik Trulsson wrote:
> > > On Thu, May 11, 2000 at 11:13:19PM +0100, Mark Ovens wrote:
> > > > Can someone clarify getopt(1) and getopts(1)? According to sh(1):
> > > > 
> > > >  getopts optstring var
> > > >      The POSIX getopts command.  The getopts command deprecates the
> > > >      older getopt(1) command.....
> > > > 
> > > > but there is no manpage for getopts(1), only getopt(1). The latter
> > > > includes some sample code which works fine, however if I change
> > > > ``getopt'' to ``getopts'' in this code I get:
> > > > 
> > > > parish:/usr/marko{89}% ./foobar -b
> > > > getopts: -b: bad variable name
> > > > Usage: ...
> > > > parish:/usr/marko{90}%
> > > > 
> > > > Since getopt(1) is deprecated it would be better to use getopts(1).
> > > > Can anyone explain the above error, or point me to some documentation
> > > > for getopts(1)?
> > > > 
> > > 
> > > On my system (4.0-stable) there is a manpage for getopts(1). It just a link
> > > to buiiltin(1) which says that it is a builtin command in sh(1).
> > 
> > Same here (I'm also on 4-stable). I hadn't spotted that it is a copy
> > of (not a link to) builtin(1).
> 
> It is a link, hardlink.
> 
>   % cd /usr/share/man/man1
>   % ls -li getopts.1.gz builtin.1.gz getopt.1.gz 
>   508294 -r--r--r--  71 root  wheel  2407 Mar 25 03:08 builtin.1.gz
>   508336 -r--r--r--   1 root  wheel  1649 Mar 25 03:10 getopt.1.gz
>   508294 -r--r--r--  71 root  wheel  2407 Mar 25 03:08 getopts.1.gz
> 

Oops!

> 
> > > The manpage for sh(1) has the following to say about getopts:
> > > 
> > >    getopts optstring var
> > >           The POSIX getopts command.  The getopts command deprecates the
> > >           older getopt(1) command.  The first argument should be a series
> > >           of letters, each possibly followed by a colon which indicates
> > >           that the option takes an argument.  The specified variable is set
> > >           to the parsed option.  The index of the next argument is placed
> > >           into the shell variable OPTIND. If an option takes an argument,
> > >           it is placed into the shell variable OPTARG. If an invalid option
> > >           is encountered, var is set to `?''. It returns a false value (1)
> > >           when it encounters the end of the options.
> > > 
> > >
> > 
> > The first couple of lines of which I quoted in my original post so,
> > yes, I have read it. However it reads as though the syntax is the same
> > as getopt(1) (at least to me it does). So the question remains; why
> > does the sample code in getopt(1) not work if I change ``getopt'' to
> > ``getopts'' in the first line?
> 
> It really is nothing like getopt(1). Not sure where it says anything
> there that would lead one to believe that.
> 

Yes, when I read it slowly several times I realized that :)

> > I'm quite happy to RTFM, if only I could find a FM to R :)
> 
> But this is a very good point. I can't find the FM, but for some
> reason, I know how to use this... It works more like getopt(3); maybe
> that's why it feels familiar.
> 
> To get about the same functionality you see in the getopt(1) manpage,
> you would have something like, 
> 
>   while getopts abo: OPT; do
>       case $OPT in
> 	  a|b)
> 	      echo flag $OPT set; sflags="${OPT#-}$sflags"
>               ;;
> 	  o)
> 	      echo oarg is "'"$OPTARG"'"; oarg="$OPTARG"
>               ;;
> 	  *)
> 	      echo ERROR
> 	      exit 2
>       esac
>   done
>   echo single-char flags: "'"$sflags"'"
>   echo oarg is "'"$oarg"'"
> 
> getopts cycles through the argument list on its own. No need to
> shift. It places the current option (the single letter) in the var
> specified. The argument of the option, if it takes one, is in
> OPTARG. Your current position on the command line is stored in OPTIND
> (and is started at the first argument if OPTIND is unset).
> 

I'd almost got there, except I didn't know that shift wasn't needed.

> Almost makes life too easy, huh?

Almost. It does seem somewhat lacking in the error handling dept.
though. Using the example code above, if you do:

	# foobar -o -a -b

then getopts(1) thinks that ``-a'' is the argument to ``-o''.

Also, if it encounters an error such as an illegal option, or a
missing argument then getopts(1) prints it's own error but sets $OPT
to ``?'' which makes it difficult to generate your own error message,
so instead of:

   # foobar -a -b -o
   No arg for -o option
   #

you could output "-o requires a valid path as an argument" which would
be easy if $OPT was set to ``o'' as you could test for $OPTARG = "" in
the o case. OK, you could probably do it by keeping track of $OPTIND,
but that points to the *next* option and if the error occurs on the
last option it is set to 1, so you need to track the previous value of
$OPTIND.

Thanks for your help.

> -- 
> Crist J. Clark                           cjclark@home.com
> 
> 
> To Unsubscribe: send mail to majordomo@FreeBSD.org
> with "unsubscribe freebsd-questions" in the body of the message

-- 
        ...and on the eighth day God created UNIX
________________________________________________________________
      FreeBSD - The Power To Serve http://www.freebsd.org
      My Webpage http://ukug.uk.freebsd.org/~mark/
mailto:mark@ukug.uk.freebsd.org             http://www.radan.com



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-questions" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20000514110900.B232>