1 #!/bin/bash
2 #
3 # Bash implements type -t.
4 #
5 # NOTE: Aliases don't work in batch mode! Interactive only.
6
7 #### getopts empty
8 set --
9 getopts 'a:' opt
10 echo "status=$? opt=$opt OPTARG=$OPTARG"
11 ## stdout: status=1 opt=? OPTARG=
12
13 #### getopts sees unknown arg
14 set -- -Z
15 getopts 'a:' opt
16 echo "status=$? opt=$opt OPTARG=$OPTARG"
17 ## stdout: status=0 opt=? OPTARG=
18
19 #### getopts three invocations
20 set -- -h -c foo
21 getopts 'hc:' opt
22 echo status=$? opt=$opt
23 getopts 'hc:' opt
24 echo status=$? opt=$opt
25 getopts 'hc:' opt
26 echo status=$? opt=$opt
27 ## stdout-json: "status=0 opt=h\nstatus=0 opt=c\nstatus=1 opt=?\n"
28
29 #### getopts resets OPTARG
30 set -- -c foo -h
31 getopts 'hc:' opt
32 echo status=$? opt=$opt OPTARG=$OPTARG
33 getopts 'hc:' opt
34 echo status=$? opt=$opt OPTARG=$OPTARG
35 ## stdout-json: "status=0 opt=c OPTARG=foo\nstatus=0 opt=h OPTARG=\n"
36
37 #### Basic getopts invocation
38 set -- -h -c foo x y z
39 FLAG_h=0
40 FLAG_c=''
41 while getopts "hc:" opt; do
42 case $opt in
43 h) FLAG_h=1 ;;
44 c) FLAG_c="$OPTARG" ;;
45 esac
46 done
47 shift $(( OPTIND - 1 ))
48 echo h=$FLAG_h c=$FLAG_c optind=$OPTIND argv=$@
49 ## stdout: h=1 c=foo optind=4 argv=x y z
50
51 #### getopts with invalid flag
52 set -- -h -x
53 while getopts "hc:" opt; do
54 case $opt in
55 h) FLAG_h=1 ;;
56 c) FLAG_c="$OPTARG" ;;
57 '?') echo ERROR $OPTIND; exit 2; ;;
58 esac
59 done
60 echo status=$?
61 ## stdout: ERROR 3
62 ## status: 2
63
64 #### getopts missing required argument
65 set -- -h -c
66 while getopts "hc:" opt; do
67 case $opt in
68 h) FLAG_h=1 ;;
69 c) FLAG_c="$OPTARG" ;;
70 '?') echo ERROR $OPTIND; exit 2; ;;
71 esac
72 done
73 echo status=$?
74 ## stdout: ERROR 3
75 ## status: 2
76
77 #### getopts doesn't look for flags after args
78 set -- x -h -c y
79 FLAG_h=0
80 FLAG_c=''
81 while getopts "hc:" opt; do
82 case $opt in
83 h) FLAG_h=1 ;;
84 c) FLAG_c="$OPTARG" ;;
85 esac
86 done
87 shift $(( OPTIND - 1 ))
88 echo h=$FLAG_h c=$FLAG_c optind=$OPTIND argv=$@
89 ## stdout: h=0 c= optind=1 argv=x -h -c y
90
91 #### getopts with explicit args
92 # NOTE: Alpine doesn't appear to use this
93 FLAG_h=0
94 FLAG_c=''
95 arg=''
96 while getopts "hc:" opt -h -c foo x y z; do
97 case $opt in
98 h) FLAG_h=1 ;;
99 c) FLAG_c="$OPTARG" ;;
100 esac
101 done
102 echo h=$FLAG_h c=$FLAG_c optind=$OPTIND argv=$@
103 ## stdout: h=1 c=foo optind=4 argv=
104
105 #### OPTIND
106 echo $OPTIND
107 ## stdout: 1
108
109 #### OPTIND after multiple getopts with same spec
110 while getopts "hc:" opt; do
111 echo '-'
112 done
113 echo $OPTIND
114
115 set -- -h -c foo x y z
116 while getopts "hc:" opt; do
117 echo '-'
118 done
119 echo $OPTIND
120
121 set --
122 while getopts "hc:" opt; do
123 echo '-'
124 done
125 echo $OPTIND
126 ## stdout-json: "1\n-\n-\n4\n1\n"
127 ## BUG mksh/osh stdout-json: "1\n-\n-\n4\n4\n"
128
129 #### OPTIND after multiple getopts with different spec
130 # Wow this is poorly specified! A fundamental design problem with the global
131 # variable OPTIND.
132 set -- -a
133 while getopts "ab:" opt; do
134 echo '.'
135 done
136 echo $OPTIND
137
138 set -- -c -d -e foo
139 while getopts "cde:" opt; do
140 echo '-'
141 done
142 echo $OPTIND
143
144 set -- -f
145 while getopts "f:" opt; do
146 echo '_'
147 done
148 echo $OPTIND
149 ## stdout-json: ".\n2\n-\n-\n5\n2\n"
150 ## BUG ash/dash stdout-json: ".\n2\n-\n-\n-\n5\n_\n2\n"
151 ## BUG mksh/osh stdout-json: ".\n2\n-\n-\n5\n5\n"
152
153 #### OPTIND narrowed down
154 FLAG_a=
155 FLAG_b=
156 FLAG_c=
157 FLAG_d=
158 FLAG_e=
159 set -- -a
160 while getopts "ab:" opt; do
161 case $opt in
162 a) FLAG_a=1 ;;
163 b) FLAG_b="$OPTARG" ;;
164 esac
165 done
166 # Bash doesn't reset optind! It skips over c! mksh at least warns about this!
167 # You have to reset OPTIND yourself.
168
169 set -- -c -d -e E
170 while getopts "cde:" opt; do
171 case $opt in
172 c) FLAG_c=1 ;;
173 d) FLAG_d=1 ;;
174 e) FLAG_e="$OPTARG" ;;
175 esac
176 done
177
178 echo a=$FLAG_a b=$FLAG_b c=$FLAG_c d=$FLAG_d e=$FLAG_e
179 ## stdout: a=1 b= c=1 d=1 e=E
180 ## BUG bash/mksh/osh stdout: a=1 b= c= d=1 e=E
181
182
183 #### Getopts parses the function's arguments
184 # NOTE: GLOBALS are set, not locals! Bad interface.
185 FLAG_h=0
186 FLAG_c=''
187 myfunc() {
188 while getopts "hc:" opt; do
189 case $opt in
190 h) FLAG_h=1 ;;
191 c) FLAG_c="$OPTARG" ;;
192 esac
193 done
194 }
195 set -- -h -c foo x y z
196 myfunc -c bar
197 echo h=$FLAG_h c=$FLAG_c opt=$opt optind=$OPTIND argv=$@
198 ## stdout: h=0 c=bar opt=? optind=3 argv=-h -c foo x y z
199