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, but bash-completion does.
93 FLAG_h=0
94 FLAG_c=''
95 arg=''
96 set -- A B C
97 while getopts "hc:" opt -h -c foo x y z; do
98 case $opt in
99 h) FLAG_h=1 ;;
100 c) FLAG_c="$OPTARG" ;;
101 esac
102 done
103 echo h=$FLAG_h c=$FLAG_c optind=$OPTIND argv=$@
104 ## STDOUT:
105 h=1 c=foo optind=4 argv=A B C
106 ## END
107
108 #### OPTIND
109 echo $OPTIND
110 ## stdout: 1
111
112 #### OPTIND after multiple getopts with same spec
113 while getopts "hc:" opt; do
114 echo '-'
115 done
116 echo $OPTIND
117
118 set -- -h -c foo x y z
119 while getopts "hc:" opt; do
120 echo '-'
121 done
122 echo $OPTIND
123
124 set --
125 while getopts "hc:" opt; do
126 echo '-'
127 done
128 echo $OPTIND
129 ## stdout-json: "1\n-\n-\n4\n1\n"
130 ## BUG mksh/osh stdout-json: "1\n-\n-\n4\n4\n"
131
132 #### OPTIND after multiple getopts with different spec
133 # Wow this is poorly specified! A fundamental design problem with the global
134 # variable OPTIND.
135 set -- -a
136 while getopts "ab:" opt; do
137 echo '.'
138 done
139 echo $OPTIND
140
141 set -- -c -d -e foo
142 while getopts "cde:" opt; do
143 echo '-'
144 done
145 echo $OPTIND
146
147 set -- -f
148 while getopts "f:" opt; do
149 echo '_'
150 done
151 echo $OPTIND
152 ## stdout-json: ".\n2\n-\n-\n5\n2\n"
153 ## BUG ash/dash stdout-json: ".\n2\n-\n-\n-\n5\n_\n2\n"
154 ## BUG mksh/osh stdout-json: ".\n2\n-\n-\n5\n5\n"
155
156 #### OPTIND narrowed down
157 FLAG_a=
158 FLAG_b=
159 FLAG_c=
160 FLAG_d=
161 FLAG_e=
162 set -- -a
163 while getopts "ab:" opt; do
164 case $opt in
165 a) FLAG_a=1 ;;
166 b) FLAG_b="$OPTARG" ;;
167 esac
168 done
169 # Bash doesn't reset optind! It skips over c! mksh at least warns about this!
170 # You have to reset OPTIND yourself.
171
172 set -- -c -d -e E
173 while getopts "cde:" opt; do
174 case $opt in
175 c) FLAG_c=1 ;;
176 d) FLAG_d=1 ;;
177 e) FLAG_e="$OPTARG" ;;
178 esac
179 done
180
181 echo a=$FLAG_a b=$FLAG_b c=$FLAG_c d=$FLAG_d e=$FLAG_e
182 ## stdout: a=1 b= c=1 d=1 e=E
183 ## BUG bash/mksh/osh stdout: a=1 b= c= d=1 e=E
184
185
186 #### Getopts parses the function's arguments
187 FLAG_h=0
188 FLAG_c=''
189 myfunc() {
190 while getopts "hc:" opt; do
191 case $opt in
192 h) FLAG_h=1 ;;
193 c) FLAG_c="$OPTARG" ;;
194 esac
195 done
196 }
197 set -- -h -c foo x y z
198 myfunc -c bar
199 echo h=$FLAG_h c=$FLAG_c opt=$opt optind=$OPTIND argv=$@
200 ## stdout: h=0 c=bar opt=? optind=3 argv=-h -c foo x y z
201
202 #### Local OPTIND
203 # minimal test case extracted from bash-completion
204 min() {
205 local OPTIND=1
206
207 while getopts "n:e:o:i:s" flag "$@"; do
208 echo "loop $OPTIND";
209 done
210 }
211 min -s
212 ## stdout: loop 2
213