cmd:getopt 

getopt typical usage 

 eval set -- `getopt -o ab:c:: -- "$@"`

 parameters '-a' does not require an argument.
 parameters '-b' requires an argument.
 parameters '-c' has an optional argument.

  while :; do
      case "$1" in
      -a) hour_enable=T ;;
      -b) shift; prefix="$1" ;; # prefix tag to add to the beg'ing of filename
      -c) shift;
        # c has an optional argument. As we are in quoted mode,
        # an empty parameter will be generated if its optional
        # argument is not found.
        case "$1" in
                "") echo "Option c, no argument";;
                *)  echo "Option c, argument \`$1'";;
        esac;;
      --) shift; break ;;
      esac
      shift
  done

Compatibilities 

BSD's getopt doesn't have optional argument, and -o switch. The (only) way to set it straight is:

    set -- `getopt ptd: "$@"`

Notes 

  1. Parameter '—' in getopt is mandatory. Otherwise:
 set -- -t -p -d 20 'ps -eo

 $ eval set -- `getopt -o ptd:: "$@"`
 getopt: invalid option -- d
 Try `getopt --help' for more information.
  1. eval is necessary. Otherwise will cause excessive quote:
 # Normal:
 $ eval set -- `getopt -o ptd:: -- "$@"`
 ++ getopt -o ptd:: -- -d -t -p 20 'ps -eaf | sort'
 + eval set -- -d ''\'''\''' -t -p -- ''\''20'\''' ''\''ps' -eaf '|' 'sort'\'''
 ++ set -- -d '' -t -p -- 20 'ps -eaf | sort'

 # No eval, excessive quote:
 $ set -- `getopt -o ptd:: -- "$@"`
 ++ getopt -o ptd:: -- -d ''\'''\''' -t -p -- ''\''20'\''' ''\''ps' -eaf '|' 'sort'\'''
 + set -- -d ''\'''\''' -t -p -- ''\'''\''\'\'''\'''\''\'\'''\'''\''' ''\'''\''\'\'''\''20'\''\'\'''\'''\''' ''\'''\''\'\'''\''ps'\''' ''\''-eaf'\''' ''\''|'\''' ''\''sort'\''\'\'''\'''\'''

NB, for previous case, "set — `getopt ptd: "$@"`", word "eval" should not be used!

getopt example: getopt-parse.bash 

#!/bin/bash

# A small example program for using the new getopt(1) program.
# This program will only work with bash(1)
# An similar program using the tcsh(1) script language can be found
# as parse.tcsh

# Example input and output (from the bash prompt):
# ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "
# Option a
# Option c, no argument
# Option c, argument `more'
# Option b, argument ` very long '
# Remaining arguments:
# --> `par1'
# --> `another arg'
# --> `wow!*\?'

# Note that we use `"$@"' to let each command-line parameter expand to a
# separate word. The quotes around `$@' are essential!
# We need TEMP as the `eval set --' would nuke the return value of getopt.
TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \
     -n 'example.bash' -- "$@"`

if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi

# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"

while true ; do
        case "$1" in
                -a|--a-long) echo "Option a" ; shift ;;
                -b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;
                -c|--c-long)
                        # c has an optional argument. As we are in quoted mode,
                        # an empty parameter will be generated if its optional
                        # argument is not found.
                        case "$2" in
                                "") echo "Option c, no argument"; shift 2 ;;
                                *)  echo "Option c, argument \`$2'" ; shift 2 ;;
                        esac ;;
                --) shift ; break ;;
                *) echo "Internal error!" ; exit 1 ;;
        esac
done
echo "Remaining arguments:"
for arg do echo '--> '"\`$arg'" ; done

optional argument 

-c|--c-long)
        # c has an optional argument. As we are in quoted mode,
        # an empty parameter will be generated if its optional
        # argument is not found.
        case "$2" in
                "") echo "Option c, no argument"; shift 2 ;;
                *)  echo "Option c, argument \`$2'" ; shift 2 ;;
        esac ;;
--) shift ; break ;;
*) echo "Internal error!" ; exit 1 ;;
$ getopt-parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "
Option a
Option c, no argument
Option c, argument `more'
Option b, argument ` very long '
Remaining arguments:
--> `par1'
--> `another arg'
--> `wow!*\?'

$ getopt-parse.bash -a par1 'another arg' --c-long='wow!*\?' -cmore -b " very long "
Option a
Option c, argument `wow!*\?'
Option c, argument `more'
Option b, argument ` very long '
Remaining arguments:
--> `par1'
--> `another arg'

$ getopt-parse.bash -m kj
example.bash: invalid option -- m
Terminating...

documented on: 2000.07.27 Thu 16:18:18

Trying history 

Trying history, 2005.02.06 

[Note]

if use -o, then need the — between options/optstring and parameters.

 $ getopt "abcd:"  -abc
  -a -b -c --

 $ getopt  -abc -o "abcd:"
 getopt: invalid option -- b
 Try `getopt --help' for more information.

 $ getopt -o "abcd:"  -- -abc
  -a -b -c --

Trying history 

    $ set -x

    $ set -- -t -p -d 20 'ps -eo '
    + set -- -t -p -d 20 'ps -eo '

    $ echo "$@"
    + echo -t -p -d 20 'ps -eo '
    -t -p -d 20 ps -eo

    $ set -- `getopt -o ptd: "$@"`
    ++ getopt -o ptd: -t -p -d 20 'ps -eo '
    + set -- -- ptd: -t -p -d 20 ps -eo

    $ echo "$@"
    + echo -- ptd: -t -p -d 20 ps -eo
    -- ptd: -t -p -d 20 ps -eo

    $ set -- -t -p -d 20 'ps -eo '
    + set -- -t -p -d 20 'ps -eo '

    $ set -- `getopt ptd: "$@"`
    ++ getopt ptd: -t -p -d 20 'ps -eo '
    + set -- -t -p -d 20 -- ps -eo

    $ echo "$@"
    + echo -t -p -d 20 -- ps -eo
    -t -p -d 20 -- ps -eo

unknown -options vs. GNU getopt 

http://www.linux.ie/old-list/47158.html

I'm writing a wrapper shell script around less(1) for various bizarre reasons that are not particularly relevant, and in the process of doing so, also experimenting with GNU getopt(1), rather than the Bourne-ish shells's builtin getopts(1).

the issue is there's a handful of -short/—long-options my script handles, and everything else (options and filenames) is to be passed on to `less'. this is relatively easy to do with a hand-coded argument parser; slightly harder but AFAIK possible with the extended `getopts' builtinto the Korn and bash shells (but not the basic one in the System V Bourne shell); but does not seem possible at all with GNU `getopt'!?

roughly speaking, GNU `getopt' takes arguments, e.g.:

-a -bc argC --foo file1 --spam=xyzzy file2

Example 1. ..and rewrites them in a quoted canonical form:

'-a' '-b' '-c' 'argC' '--foo' '--spam' 'xyzzy' '--' 'file1' 'file2'

..according to a specification. in the example above, that. specification must have said `-a' and `-b' are valueless short options, `-c' is a short option which takes a value, `—foo' is a valueless long option, and `—spam' is a long option which takes a value:

unset GETOPT_COMPATIBLE POSIXLY_CORRECT
getopt -o abc: -l foo,spam: ...

so far so good. however, if an unknown option-looking-arg (one which starts with a `-') is encountered, I cannot find any way of telling GNU `getopt' to treat it as just another string to position after the `' in the rewritten form. e.g., if `—foo' in the above was *not* part of the spec, then I want `getopt' to rewrite the arguments to be:

'-a' '-b' '-c' 'argC' '--spam' 'xyzzy' '--' '--foo' 'file1' 'file2'

unknown -options vs. GNU getopt 

..but there does not appear to be any way of doing this!? The trick is to set POSIXLY_CORRECT:

 $ getopt -o abc: -l spam: -- -a -bc argC --spam=xyzzy file1 --foo file2
 getopt: unrecognized option `--foo'
  -a -b -c 'argC' --spam 'xyzzy' -- 'file1' 'file2'

 $ POSIXLY_CORRECT=1 getopt -o abc: -l spam: -- -a -bc argC --spam=xyzzy file1 --foo file2
  -a -b -c 'argC' --spam 'xyzzy' -- 'file1' '--foo' 'file2'

However, it is not perfect:

 $ POSIXLY_CORRECT=1 getopt -o abc: -l spam: -- -a -bc argC --spam=xyzzy --foo file2
 getopt: unrecognized option `--foo'
  -a -b -c 'argC' --spam 'xyzzy' -- 'file2'

I.e., there has to be a non-'-'-beginning string before —foo.

NB,

  • If the first character is `+', or if the environment variable POSIXLY_CORRECT is set, parsing stops as soon as the first non-option parameter (ie. a parameter that does not start with a '-') is found that is not an option argument. The remaining parameters are all interpreted as non-option parameters.
  • Each parameter not starting with a '-', and not a required argument of a previous option, is a non-option parameter. Each parameter after a '—' parameter is always interpreted as a non-option parameter. If the environment variable POSIXLY_CORRECT is set, or if the short option string started with a `+', all remaining parameters are interpreted as non-option parameters as soon as the first non-option parameter is found.

T

documented on: 2005.02.06

unknown -options vs. GNU getopt 

From getopt.c:

As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order.

Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard.

GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments.

getopt, What's the right way to use 

Newsgroups: comp.os.linux.misc,comp.unix.shell
Date: Thu, 13 Mar 2003 02:07:12 GMT

Thanks every one who replied, but the problem is that I'm writing a /bin/sh script. That's why I have to use getopt instead of getopts. The replies are either for bash or ksh. So, literately the problem is still not solved.

Does anyone have an answer to this? Thanks

> What's the right way to use getopt in shell scripts?
>
> In my script I have:
>
> fhelp(){
>   # show help
>   exit
> }
>
>   set -- `getopt "ad:p:s:" "$@"` || fhelp
>
> But this doesn't catch the wrong options. My script just prompted
>
> getopt: invalid option -- x

T

getopt, the right way to use 

>        Example scripts for (ba)sh and (t)csh  are  provided  with
>        the  getopt(1)  distribution, and are optionally installed
>        in /usr/local/lib/getopt or /usr/lib/getopt.

Example scripts are *optionally* installed, which are not included in any rpm distribution. Took me quite a while to find them…

http://www.kernel.org/pub/linux/utils/util-linux/
http://huizen.dds.nl/~frodol/getopt.html

Just for the archive. The answer is actually quite simple:

,-----
| # We need TEMP as the `eval set --' would nuke the return value of getopt.
| TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \
|      -n 'example.bash' -- "$@"`
|
| if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
|
| eval set -- "$TEMP"
`-----

T

getopt, the right way to use 

 $ set -- -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "

 $ echo "$@"
 -a par1 another arg --c-long wow!*\? -cmore -b  very long

 $ eval set -- `getopt -o ab:c:: --long a-long,b-long:,c-long:: -n 'example.bash' -- "$@"`

 $ echo "$@"
 -a --c-long  -c more -b  very long  -- par1 another arg wow!*\?