-
Notifications
You must be signed in to change notification settings - Fork 5
/
options
executable file
·75 lines (65 loc) · 2.3 KB
/
options
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/bin/bash
# This is how I manually parse options for complex shell scripts. The first
# loop, even though it uses 'optstring', will NOT check if an option that takes
# a required argument has said argument provided. That must be done within the
# second loop and case statement, yourself. Its purpose is solely to determine
# that -oARG is split into -o ARG, and not -o -A -R -G.
# Some scripts that use this method, for examples of usage:
# https://github.com/e36freak/tools/blob/master/newscript
# https://github.com/e36freak/clearcache/blob/master/clearcache
#
# A modified version that allows optional arguments (by not altering --long=arg
# in the inital loop):
# https://github.com/e36freak/meat/blob/master/meat
################################################################################
# option string, for short options.
# very much like getopts, any option followed by a ':' takes a required arg
optstring=h
# iterate over options, breaking -ab into -a -b and --foo=bar into --foo bar
# also turns -- into --endopts to avoid issues with things like '-o-', the '-'
# should not indicate the end of options, but be an invalid option (or the
# argument to the option, such as wget -qO-)
unset options
while (($#)); do
case $1 in
# if option is of type -ab
-[!-]?*)
# loop over each character starting with the second
for ((i=1; i<${#1}; i++)); do
c=${1:i:1}
# add current char to options
options+=("-$c")
# if option takes a required argument, and it's not the last char
# make the rest of the string its argument
if [[ $optstring = *"$c:"* && ${1:i+1} ]]; then
options+=("${1:i+1}")
break
fi
done
;;
# if option is of type --foo=bar, split on first '='
--?*=*) options+=("${1%%=*}" "${1#*=}");;
# end of options, stop breaking them up
--)
options+=(--endopts)
shift
options+=("$@")
break
;;
# otherwise, nothing special
*) options+=("$1");;
esac
shift
done
# set new positional parameters to altered options
set -- "${options[@]}"
unset options
# actually parse the options and do stuff
while [[ $1 = -?* ]]; do
case $1 in
-h|--help) usage >&2; exit 0;;
--endopts) shift; break;;
*) die "invalid option: $1";;
esac
shift
done