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
BSD's getopt doesn't have optional argument, and -o switch. The (only) way to set it straight is:
set -- `getopt ptd: "$@"`
set -- -t -p -d 20 'ps -eo $ eval set -- `getopt -o ptd:: "$@"` getopt: invalid option -- d Try `getopt --help' for more information.
# 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!
#!/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
-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
![]() | |
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 --
$ 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
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'
..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,
T
documented on: 2005.02.06
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.
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
> 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
$ 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!*\?