Usage: argp [OPTION...] [--] [args ...] A wrapper for getopt(1) which simulates argp(3) for bash. Normally other scripts pipe their option descriptions in here for automatic help and man-page production and for generating the code for getopt(1). Requires bash-3+. See also argp(1) which is a binary (and much faster) version of this. See http://sourceforge.net/projects/argpsh See http://bhepple.freeshell.org/oddmuse/wiki.cgi/argp.sh It buys you: o all the goodness of getopt o define options in one central place together with descriptions using a simple flat file format or XML. o fewer 'magic' and duplicated values in your code o automatic consistency between the getopt calling parameters, the case statement processing the user's options and the help/man pages o less spaghetti in your own code o easier to maintain o help-page and man-page printing - all from the same data sources o checking of option consistency at runtime o range checking of option values at runtime o pretty easy to use o portable to OS's without long option support - the help page adapts too ############################################################################### Usage: argp.sh / argp reads its configuration from stdin (fd0) (see below for details) and outputs the following: * --help output on stdout fd1 * errors on stderr fd2 * a list of commands on fd3 The calling program can then 'eval' that list of commands in order to set environment variables as set by the user in command line options. Also, any remaining arguments after the options are removed are set to $1 $2 ... eg. if the user typed 'myprog --foobar --barfoo=three a b c' then after 'eval'ing the fd3 output of argp.sh / argp you would have FOOBAR="set" BARFOO="three" $1 $2 ... = a b c Usually, the calling program would invoke argp.sh / argp like this: exec 4>&1 eval "$(echo "$ARGS" | argp.sh "$@" 3>&1 1>&4 || echo exit $? )" exec 4>&- Here's a bit of an explanation in case you're interested: exec 4>&1 # make fd4 a copy of fd1 stdout eg /dev/pts/0, the terminal eval $( # inside this sub-shell fd1 is now a pipe echo "$ARGS" | # 3>&1: connect fd3 to fd1 (the pipe) so that anything printed # on fd3 is fed to the pipe (and eventually eval'd). # # 1>&4: fd1 is connected to fd4 ie /dev/pts/0 so that anything # that argp.sh / argp prints on stdout (eg the --help output) ends up # on the terminal: argp.sh "$@" 3>&1 1>&4 || echo exit $? ) exec 4>&- # close fd4 ############################################################################### It's easier to look at a running script but here's the manual: ############################################################################### this is a comment. # The following line defines our program name. We might also write # this as ARGP_PROG=$(basename $0): ARGP_PROG=my-script # '--quiet' is a built-in option, but we normally delete it if 'verbose' is # supported. ARGP_DELETE=quiet # this defines the program's version string to be displayed by the -V option: ARGP_VERSION=1.6 # this string is added as a prefix to all option names on output, eg if you need to use an option that clashes with a system environment parameter eg --home: ARGP_PREFIX=FOO_ # if this is set then multiple invocations of a string or array option will # be concatenated using this separator eg '-s s -s b' will give 'a:b' ARGP_OPTION_SEP=: # Here are the options that this program will accept: ######## ##### ### #### ##### ########### # name sname arg type range description ######## ##### ### #### ##### ########### name=default : 'name' must be present and unique. 'default' must be given but may be '' sname : the single-letter short name of the option (use '' if a short name is not needed) arg : the name of the argument to be used in --help (not for booleans) type : b (boolean), i (integer), d (double), s[:] (string), a[:] (array) or u (url). Default is boolean if arg is not given, otherwise string. If a boolean is initialised to '0', then it is incremented every time it is given. If a boolean is initialised to anything else then it flips between 'default' and 'range' every time it is given. If 's:' or 'a:' then ':' overrides ARGP_OPTION_SEP for this option. Any syntactically clean string can be used instead of ':' ie not ' or ". range : for numeric options: min:max eg 1.2:4.5 or min-max eg 1-3 for string options: an extended regexp for array options: a space separated list of alternates in quotes "..." or '...' for boolean options: the value to assign the option when set desc : leave empty for hidden options. Long descriptions can span lines by putting '\' at the end of the line and by terminated the description with a '.' in the first column. ############################################################################### xamples: # This is the simplest possible option definition. It specifies a # hidden option (--hidden) which does not appear in the help or man # pages. It defaults to being a simple flag (boolean) with a default # value of '' and 'set' if --hidden is on the command line. HIDDEN= # a boolean option with a short name and a numeric default which is # incremented every time the --bool, -b option is given: BOOL='0' b '' b '' description of this option # this is a (boolean) flag which gets set to the string 'foobar' when # --flag, -f is on the command line otherwise it is set to 'barfoo': FLAG='barfoo' f '' b 'foobar' a flag # here is an integer value option which must sit in a given range: INT=1 i units i '1:3' an integer. # here is an array value ie just a string which must take one of # the values in the 'range': ARRAY=a a widgets a 'a b' an array # this option is a simple string which will be checked against a regex(7): STRING='' s string s '^foo.*bar$|^$' a string. # a double value which is checked against a range: DOUBLE=1 d miles d 0.1:1.3 a double. # this is a URL which will be checked against the URL regex and has a # default value URL='http://www.foobar.com' u url u '' a url. # delete this one as we want to use the 'q' option for something else: ARGP_DELETE=quiet # this uses the same short letter 'q' as the --quiet option which was # deleted above QUAINT='' q '' s '' a quaint description # here we define the non-option arguments that the command takes: ARGP_ARGS= [--] [args] ARGP_SHORT=This is a short description for the first line of the man page. ARGP_USAGE= This is a longer description. Spring the flangen dump. Spring the flingen dump. Spring the flangen dump. Spring the flingen dump. ############################################################################### XML can also be instead of the above (provided xmlstarlet is available): fs [--] [pattern] Search for filenames in sub-directories. quiet 1.2 FOO_ Presently this is just a shorthand for: find . -follow \$EXCLUDE -type $TYPE -name '*pattern*' -print 2>/dev/null |sort Note that the attribute 'name' is required - the others are all optional. Also the option value should be on a single line (the program usage can be on multiple lines). ############################################################################### Note that --verbose, --help, --quiet and --version options will be added automatically. Also, a hidden option '--print-man-page' is provided to print a skeleton man(1) page which can be used as the starting point for a full man page. Another hidden option '--print-xml' prints out the XML equivalent of the argp input. If POSIXLY_CORRECT is set, then option parsing will end on the first non-option argument (eg like ssh(1)). ############################################################################### Here is a sample of the output when the command is called with --help: Usage: my-script [OPTION...] [--] [args] This is a longer description. Spring the flangen dump. Spring the flingen dump. Spring the flangen dump. Spring the flingen dump." Options: -a, --array= an array Must be of type 'a'. Must be in the range 'a b'. -b, --bool description of this option -d, --double= a double. Must be of type 'd'. Must be in the range '0.1-1.3'. -f, --flag a flag -i, --int= an integer. Must be of type 'i'. Must be in the range '1-3'. -q, --quaint a quaint description Must fit the regex ''. -s, --string= a string. Must fit the regex '^foo.*bar$|^$'. -u, --url= a url. Must fit the regex '^(nfs|http|https|ftp|file)://[[:alnum:]_.-]*[^[:space:]]*$'. -v, --verbose be verbose -h, --help print this help message -V, --version print version and exit Options: -q, --quiet be quiet -v, --verbose be verbose -h, --help print this help message -V, --version print version and exit